Ich möchte, dass eine bestimmte Operation für eine bestimmte Zeit ausgeführt wird. Wenn diese Zeit abgelaufen ist, senden Sie einen weiteren Ausführungsbefehl.
%Vor%Anstatt eine Ruhezustandsanweisung zu haben, die den Rest der Anwendung blockiert, wie kann ich das mit einem Async / Task / Await in C # schreiben?
Dieses Problem wurde von Joe Hoag 2011 im Blog des Parallel Teams beantwortet: Erstellen einer Task.TimeoutAfter-Methode
Die Lösung verwendet eine TaskCompletionSource und enthält mehrere Optimierungen (12% nur durch Vermeidung von Captures), behandelt Bereinigungen und behandelt Randfälle wie das Aufrufen von TimeoutAfter, wenn die Zieltask bereits abgeschlossen wurde, gibt ungültige Timeouts aus.
Das Schöne an Task.TimeoutAfter ist, dass es sehr einfach ist, es mit anderen Fortsetzungen zu kombinieren, denn es macht nur eine einzige Sache: benachrichtigt Sie, dass das Timeout abgelaufen ist. Es versucht nicht, Ihre Aufgabe abzubrechen. Sie können entscheiden, was zu tun ist, wenn eine TimeoutException ausgelöst wird.
Eine schnelle Implementierung mit async/await
von Stephen Toub wird ebenfalls vorgestellt, obwohl Edge Cases ebenfalls nicht behandelt werden.
Die optimierte Implementierung ist:
%Vor%und Stephen Toubs Implementierung, ohne auf Kantenfälle zu prüfen:
%Vor%So würde ich es machen, indem ich das Muster zum Abbrechen von Aufgaben (die Option ohne zu werfen) verwenden würde eine Ausnahme).
[EDITED] Wurde aktualisiert, um den Vorschlag von Svick zu verwenden, um das Timeout über CancellationTokenSource
Konstruktor .
So rufen Sie es über eine asynchrone Methode auf:
%Vor%So rufen Sie es aus einer regulären Methode auf und behandeln die Beendigung asynchron:
%Vor%Angenommen, StartDoingStuff und StopDoingStuff wurden als Async-Methoden erstellt, die Task zurückgeben, dann
%Vor%BEARBEITEN: Wenn der ursprüngliche Fragesteller eine asynchrone Methode wünscht, die nach einer bestimmten Periode abbricht: Angenommen, die Methode würde keine Netzwerkanforderungen stellen, sondern lediglich eine Verarbeitung im Speicher durchführen und das Ergebnis willkürlich ohne Berücksichtigung ihrer Auswirkungen abbrechen, dann eine Annullierung verwenden Token:
%Vor%BEARBEITEN : Ich hätte erwähnen sollen, dass Sie die resultierende OperationCanceledException abfangen können, die anzeigt, wie die Aufgabe beendet wurde, wodurch Sie nicht mit Bools herumalbern müssen.
Tags und Links .net c# multithreading async-await