Diese Frage gefällt mir sehr gut:
Einfachste Möglichkeit, eine Feuer- und Vergessensmethode in C # durchzuführen?
Ich möchte nur wissen, dass es jetzt, da wir parallele Erweiterungen in C # 4.0 haben, eine sauberere Möglichkeit gibt, Fire & Forget mit parallel linq auszuführen.
c#
.net
.net-4.0
task-parallel-library
fire-and-forget
Jonathon Kresner
quelle
quelle
Antworten:
Keine Antwort für 4.0, aber erwähnenswert, dass Sie dies in .Net 4.5 noch einfacher machen können mit:
Das Pragma besteht darin, die Warnung zu deaktivieren, die besagt, dass Sie diese Aufgabe als Feuer ausführen und vergessen.
Wenn die Methode in geschweiften Klammern eine Aufgabe zurückgibt:
Lassen Sie uns das zusammenfassen:
Task.Run gibt eine Task zurück, die eine Compiler-Warnung (Warnung CS4014) generiert, die darauf hinweist, dass dieser Code im Hintergrund ausgeführt wird - genau das wollten Sie, daher deaktivieren wir die Warnung 4014.
Standardmäßig versuchen Aufgaben, "auf den ursprünglichen Thread zurückzugreifen". Dies bedeutet, dass diese Aufgabe im Hintergrund ausgeführt wird, und versuchen dann, zu dem Thread zurückzukehren, der sie gestartet hat. Oft feuern und vergessen Aufgaben werden beendet, nachdem der ursprüngliche Thread fertig ist. Dadurch wird eine ThreadAbortException ausgelöst. In den meisten Fällen ist dies harmlos - es sagt Ihnen nur, ich habe versucht, mich wieder anzuschließen, ich habe versagt, aber es ist Ihnen sowieso egal. Aber es ist immer noch etwas laut, ThreadAbortExceptions entweder in Ihren Protokollen in Production oder in Ihrem Debugger in local dev zu haben.
.ConfigureAwait(false)
ist nur eine Möglichkeit, ordentlich zu bleiben und explizit zu sagen, dies im Hintergrund auszuführen, und das war's.Da dies wortreich ist, insbesondere das hässliche Pragma, verwende ich dafür eine Bibliotheksmethode:
Verwendung:
quelle
ConfigureAwait(false)
auf ,Task.Run
wenn Sie nichtawait
die Aufgabe. Der Zweck der Funktion liegt in ihrem Namen: "configure await ". Wenn Sieawait
die Aufgabe nicht ausführen, registrieren Sie keine Fortsetzung, und es gibt keinen Code für die Aufgabe, wie Sie sagen, "zurück zum ursprünglichen Thread zu marshallen". Das größere Risiko besteht darin, dass eine unbeobachtete Ausnahme im Finalizer-Thread erneut ausgelöst wird, auf die diese Antwort nicht einmal eingeht.#Disable Warning BC42358
Mit dem
Task
Klasse ja, aber PLINQ ist wirklich zum Abfragen über Sammlungen.So etwas wie das Folgende wird es mit Task machen.
Oder auch...
Oder...
Wo
FireAway
istAufgrund der Knappheit des Klassen- und Methodennamens übertrifft dies die Threadpool-Version um sechs bis neunzehn Zeichen, je nachdem, welches Sie auswählen :)
quelle
fire and forget in ASP.NET WebForms and windows.close()
?Ich habe ein paar Probleme mit der führenden Antwort auf diese Frage.
Erstens, in einer echten Feuer-und-Vergessen- Situation werden Sie
await
die Aufgabe wahrscheinlich nicht erledigen, so dass es sinnlos ist, sie anzuhängenConfigureAwait(false)
. Wenn Sie nichtawait
den von zurückgegebenen WertConfigureAwait
, kann dies möglicherweise keine Auswirkung haben.Zweitens müssen Sie wissen, was passiert, wenn die Aufgabe mit einer Ausnahme abgeschlossen wird. Betrachten Sie die einfache Lösung, die @ ade-miller vorgeschlagen hat:
Dies birgt eine Gefahr: Wenn eine nicht behandelte Ausnahme auftritt
SomeMethod()
, wird diese Ausnahme niemals beobachtet und möglicherweise 1 im Finalizer-Thread erneut ausgelöst, wodurch Ihre Anwendung abstürzt. Ich würde daher empfehlen, eine Hilfsmethode zu verwenden, um sicherzustellen, dass alle daraus resultierenden Ausnahmen eingehalten werden.Sie könnten so etwas schreiben:
Diese Implementierung sollte einen minimalen Overhead haben: Die Fortsetzung wird nur aufgerufen, wenn die Aufgabe nicht erfolgreich abgeschlossen wurde, und sie sollte synchron aufgerufen werden (anstatt getrennt von der ursprünglichen Aufgabe geplant zu werden). Im "faulen" Fall erhalten Sie nicht einmal eine Zuweisung für den Fortsetzungsdelegierten.
Das Starten einer asynchronen Operation wird dann trivial:
1. Dies war das Standardverhalten in .NET 4.0. In .NET 4.5 wurde das Standardverhalten so geändert, dass nicht beobachtete Ausnahmen im Finalizer-Thread nicht erneut ausgelöst werden (obwohl Sie sie möglicherweise weiterhin über das Ereignis UnobservedTaskException in TaskScheduler beobachten). Die Standardkonfiguration kann jedoch überschrieben werden, und selbst wenn Ihre Anwendung .NET 4.5 erfordert, sollten Sie nicht davon ausgehen, dass nicht beobachtete Aufgabenausnahmen harmlos sind.
quelle
ContinueWith
aufgrund einer Stornierung aufgerufen wurde, ist die Ausnahmeeigenschaft des Antezedens Null und eine Nullreferenzausnahme wird ausgelöst. Wenn Sie die Option zur Fortsetzung der Aufgabe aufOnlyOnFaulted
festlegen, müssen Sie die Nullprüfung nicht mehr durchführen oder prüfen, ob die Ausnahme null ist, bevor Sie sie verwenden.Task
zu einem Implementierungsdetail.Task
nicht beobachtet " ist nicht dasselbe wie "Ich möchte einen einfachen Weg, um eine Hintergrundoperation zu starten, niemals das Ergebnis zu beobachten, und es ist mir egal, welcher Mechanismus verwendet wird es zu tun." Auf dieser Grundlage stehe ich hinter meiner Antwort auf die gestellte Frage .fire and forget
in ASP.NET WebForms undwindows.close()
?Nur um ein Problem zu beheben, das mit der Antwort von Mike Strobel auftreten wird:
Wenn Sie
var task = Task.Run(action)
diese Aufgabe verwenden und nachdem Sie ihr eine Fortsetzung zugewiesen haben, besteht die Gefahr, dassTask
Sie eine Ausnahme auslösen, bevor Sie der eine Ausnahmebehandlungsfortsetzung zuweisenTask
. Die folgende Klasse sollte also frei von diesem Risiko sein:Hier wird das
task
nicht direkt ausgeführt, sondern erstellt, eine Fortsetzung zugewiesen, und erst dann wird die Aufgabe ausgeführt, um das Risiko auszuschließen, dass die Aufgabe die Ausführung abschließt (oder eine Ausnahme auslöst), bevor eine Fortsetzung zugewiesen wird.Die
Run
Methode hier gibt die Fortsetzung zurück,Task
sodass ich Komponententests schreiben kann, um sicherzustellen, dass die Ausführung abgeschlossen ist. Sie können es jedoch bei Ihrer Verwendung ignorieren.quelle