2013-08-29 8 views
5

Die ursprüngliche Methode Berufung ist wie:Ablaufen ein Methodenaufruf

public string AskAPI(string uri) 
{ 
    return api.Query(uri); 
} 

wo die api einfach eine importierte DLL Referenz.

Im Moment möchte ich ein Timeout-Feature zur AskAPI-Methode hinzufügen, so dass AskAPI eine Ausnahme auslöst, wenn die api.Query länger dauert als, sagen wir 30 Sekunden.

Scheint, ich werde es nicht funktionieren lassen. Kann jemand seine Gedanken darüber teilen?

Danke!

+0

Sie müssten in der Lage sein, 'api.Query' zu modifizieren, um Timeout-Funktionalität hinzuzufügen. Da Sie keine Informationen darüber haben, was es ist, ist es unmöglich, Ihnen zu sagen, wie es geht. (Es gibt keine Möglichkeit, um den Anruf herumzukommen, da Sie keine Möglichkeit haben, den Anruf aufgrund dessen, was Sie hier gepostet haben, zu unterbrechen.) –

+0

@KenWhite api.Query ist auch nicht in meiner Kontrolle. Du meinst, ohne es zu bearbeiten, kann ich AskAPI-Methode nicht auslaufen? – jamesdeath123

+0

Ich kann das nicht beantworten, weil Sie genau drei Codezeilen ('{}' zählt nicht) völlig außerhalb des Kontextes, mit absolut keinen anderen Informationen zur Verfügung gestellt haben. Basierend auf genau was du gepostet hast, wäre die Antwort "Nein, du kannst nicht". –

Antwort

8

Sie Tasks dies zu tun, verwenden könnte, hier ein Beispiel:

public string AskAPI(string uri, int millis) 
{ 
    using (var task = new Task<string>(() => api.Query(uri))) 
    { 
     task.Start(); 
     task.Wait(millis); 
     if (!task.IsCompleted) throw new TimeoutException(); 
     return task.Result; 
    } 
} 

Dank Guillaume für das Vorschlagen einer Timeout zu verwenden.

Aber wie Jim Mischel hervorhebt, wird dies die Ausführung der Aufgabe nicht verhindern. In diesem Fall wäre es am besten, wenn Sie die API, die Sie aufrufen, modifizieren, denn dann können Sie die CancellationToken-Klasse voll nutzen was für diese Art von Dingen gemacht wurde.

Andere als die, die einzige andere schnelle Lösung, die ich denken kann (was nicht ratsam sein kann) wäre, das Verfahren zu umwickeln (oder kombinieren) mit etwas wie folgt aus:

public T Await<T>(Func<T> fun, int millis) 
{ 
    using (var cancel = new CancellationTokenSource(millis)) 
    using (var task = new Task<T>(() => 
    { 
     T result = default(T); 
     var thread = new Thread(() => result = fun()); 
     thread.Start(); 
     while (!cancel.Token.IsCancellationRequested && thread.IsAlive) ; // Wait for a sign from above 
     thread.Abort(); 
     cancel.Token.ThrowIfCancellationRequested(); 
     return result; 
    }, cancel.Token)) 
    { 
     task.Start(); 
     task.Wait(millis); 
     cancel.Cancel(); 
     if (!task.IsCompleted) throw new TimeoutException(); 
     return task.Result; 
    } 
} 

Und dann rufen Verwenden:

Await(() => AskAPI("http://some.uri"), 30000); 
+1

Nicht "Exception" werfen. Throw 'TimeoutException'. – Guillaume

+1

@Guillaume Danke dafür, ich hätte mir die Zeit nehmen sollen, nachzusehen. =) – sgbj

+2

Aber die Aufgabe wird weiterhin ausgeführt, oder? Das heißt, "api.Query" wird nicht abgebrochen? –