Dies ist kein Duplikat von "So rufen Sie eine asynchrone Methode sicher in C # auf, ohne zu warten" .
Wie unterdrücke ich die folgende Warnung?
Warnung CS4014: Da dieser Aufruf nicht erwartet wird, wird die Ausführung der aktuellen Methode fortgesetzt, bevor der Aufruf abgeschlossen ist. Wenden Sie den Operator "Warten" auf das Ergebnis des Anrufs an.
Ein einfaches Beispiel:
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Was ich versucht habe und nicht mochte:
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
Aktualisiert , da die ursprünglich akzeptierte Antwort bearbeitet wurde, habe ich die akzeptierte Antwort in die Antwort mit C # 7.0-Rückwürfen geändert , da ich dies hier nicht für ContinueWith
angemessen halte . Wann immer ich Ausnahmen für Feuer-und-Vergessen-Operationen protokollieren muss, verwende ich einen ausgefeilteren Ansatz, den Stephen Cleary hier vorgeschlagen hat .
quelle
#pragma
ist nicht schön?async void
Hilfsmethode.Antworten:
Mit C # 7 können Sie jetzt Rückwürfe verwenden :
quelle
_ = ...
in meinem Gehirn.#pragma warning disable CSxxxx
hässlicher aussieht als das Verwerfen;)Sie können eine Erweiterungsmethode erstellen, die die Warnung verhindert. Die Erweiterungsmethode kann leer sein oder Sie können dort eine Ausnahmebehandlung hinzufügen
.ContinueWith()
.jedoch ASP.NET zählt die Anzahl der laufenden Tasks, so wird es nicht funktionieren mit der einfachen
Forget()
Erweiterung wie oben aufgeführt und stattdessen mit Ausnahme fehlschlagen:Mit .NET 4.5.2 kann es gelöst werden mit
HostingEnvironment.QueueBackgroundWorkItem
:quelle
TplExtensions.Forget
. Es gibt viel mehr Güte unterMicrosoft.VisualStudio.Threading
. Ich wünschte, es wäre für die Verwendung außerhalb von Visual Studio SDK verfügbar.Sie können die Methode mit dem folgenden Attribut dekorieren:
Grundsätzlich sagen Sie dem Compiler, dass Sie wissen, was Sie tun, und dass er sich keine Gedanken über mögliche Fehler machen muss.
Der wichtige Teil dieses Codes ist der zweite Parameter. Der Teil "CS4014:" unterdrückt die Warnung. Sie können alles schreiben, was Sie wollen.
quelle
[SuppressMessage("Compiler", "CS4014")]
unterdrückt die Nachricht im Fenster Fehlerliste, aber das Ausgabefenster zeigt immer noch eine WarnzeileMeine zwei Möglichkeiten, damit umzugehen.
Speichern Sie es in einer Discard-Variablen (C # 7).
Beispiel
_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);
Seit der Einführung von Rückwürfen in C # 7 halte ich dies nun für besser als die Unterdrückung der Warnung. Weil es nicht nur die Warnung unterdrückt, sondern auch die Feuer-und-Vergessen-Absicht klar macht.
Darüber hinaus kann der Compiler es im Release-Modus optimieren.
Unterdrücke es einfach
ist eine nette Lösung, um "zu feuern und zu vergessen".
Der Grund, warum diese Warnung vorhanden ist, liegt darin, dass Sie in vielen Fällen nicht beabsichtigen, eine Methode zu verwenden, die eine Aufgabe zurückgibt, ohne darauf zu warten. Es ist sinnvoll, die Warnung zu unterdrücken, wenn Sie feuern und vergessen möchten.
Wenn Sie Probleme haben, sich daran zu erinnern, wie man buchstabiert
#pragma warning disable 4014
, lassen Sie es einfach von Visual Studio hinzufügen. Drücken Sie Strg +. um "Schnellaktionen" und dann "CS2014 unterdrücken" zu öffnenAlles in allem
Es ist dumm, eine Methode zu erstellen, deren Ausführung einige weitere Ticks erfordert, nur um eine Warnung zu unterdrücken.
quelle
[MethodImpl(MethodImplOptions.AggressiveInlining)] void Forget(this Task @this) { } /* ... */ obj.WorkAsync().Forget();
AggressiveInlining
den Compiler benutze, ignoriert er es einfach aus irgendeinem Grund#pragma warning disable 4014
und anschließend die Warnung mit wiederherzustellen#pragma warning restore 4014
. Es funktioniert immer noch ohne den Fehlercode, aber wenn Sie die Fehlernummer nicht hinzufügen, werden alle Meldungen unterdrückt.Eine einfache Möglichkeit, die Warnung zu stoppen, besteht darin, die Aufgabe beim Aufrufen einfach zuzuweisen:
Und so würden Sie in Ihrem ursprünglichen Beitrag Folgendes tun:
quelle
task
wie eine vergessene lokale Variable aussieht. Fast so, wie der Compiler mir eine weitere Warnung geben sollte, wird so etwas wie "task
zugewiesen, aber sein Wert wird nie verwendet", außerdem nicht. Außerdem ist der Code dadurch weniger lesbar. Ich selbst benutze diesen Ansatz.fireAndForget
nenne ... also erwarte ich, dass es von nun an nicht mehr referenziert wird.Der Grund für die Warnung ist, dass WorkAsync eine zurückgibt
Task
, die niemals gelesen oder erwartet wird. Sie können den Rückgabetyp von WorkAsync auf festlegenvoid
und die Warnung wird .In der Regel gibt eine Methode a zurück,
Task
wenn der Anrufer den Status des Arbeiters kennen muss. Im Falle eines Fire-and-Forget sollte void zurückgegeben werden, um zu ähneln, dass der Aufrufer von der aufgerufenen Methode unabhängig ist.quelle
Warum nicht in eine asynchrone Methode einbinden, die void zurückgibt? Ein bisschen langwierig, aber alle Variablen werden verwendet.
quelle
Ich habe diesen Ansatz heute zufällig gefunden. Sie können einen Delegaten definieren und dem Delegaten zuerst die asynchrone Methode zuweisen.
und nenne es so
...
Ich fand es interessant, dass der Compiler bei Verwendung des Delegaten nicht genau dieselbe Warnung ausgibt.
quelle
(new Func<Task>(AsyncOperation))()
obwohl IMO immer noch etwas zu ausführlich ist.