Ich möchte eine fertige Task
(nicht Task<T>
) erstellen . Ist in .NET etwas eingebaut, um dies zu tun?
Eine verwandte Frage: Erstellen Sie eine abgeschlossene Aufgabe <T>
c#
.net
async-await
task-parallel-library
Timothy Shields
quelle
quelle
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.
Welche Probleme hat das Ihrer Meinung nach? Wenn Sie einen einzelnen zwischenspeichern, belegtTask
Ihr gesamtes Programm ein zusätzliches Stück Speicher. Das ist nichts . Man könnte auch eine erledigte Aufgabe erstellen, ohne das zu tun, es wäre einfach nicht besser.ValueTask
für abgeschlossene Aufgaben gibt (dh für Werte, die Sie bereits haben, damit der Code im Wesentlichen synchron ist), wodurch Sie eine Zuordnung sparen.Antworten:
Die neueste Version von .Net (v4.6) fügt genau das hinzu, eine integrierte Task.CompletedTask :
Diese Eigenschaft ist als No-Lock-Singleton implementiert, sodass Sie fast immer dieselbe abgeschlossene Aufgabe verwenden würden.
quelle
Task.CompletedTask
ist noch intern.Task<T>
ist implizit konvertierbar inTask
, also holen Sie sich einfach eine vollständigeTask<T>
(mit einemT
beliebigen Wert) und verwenden Sie diese. Sie können so etwas verwenden, um die Tatsache zu verbergen, dass irgendwo ein tatsächliches Ergebnis vorliegt.Beachten Sie, dass wir eine einzelne Aufgabe zwischenspeichern und wiederverwenden können, da wir das Ergebnis nicht verfügbar machen und die Aufgabe immer abgeschlossen ist.
Wenn Sie .NET 4.0 verwenden und nicht haben
FromResult
, können Sie Ihre eigenen erstellen mitTaskCompletionSource
:quelle
Meine bevorzugte Methode hierfür ist das Aufrufen
Task.WhenAll()
ohne Argumente. In der MSDN-Dokumentation heißt es: "Wenn das bereitgestellte Array / die Aufzählung keine Aufgaben enthält, wechselt die zurückgegebene Aufgabe sofort in einen RanToCompletion-Status, bevor sie an den Aufrufer zurückgegeben wird." Das klingt nach dem, was du willst.Update: Ich habe die Quelle bei Microsoft's Reference Source gefunden . Dort können Sie sehen, dass Task.WhenAll Folgendes enthält:
Task.CompletedTask ist also zwar intern, wird jedoch durch Aufrufen von WhenAll () ohne Argumente verfügbar gemacht.
quelle
Ich würde verwenden
Task.Delay(0)
. Intern wird eine zwischengespeicherte Instanz eines abgeschlossenen Objekts zurückgegebenTask<T>
. Dies ist genau das, was die aktuelle Antwort ohnehin vorschlägt. Nur jetzt müssen Sie weder eine Instanz selbst zwischenspeichern, noch haben Sie unelegante Müllwerte in Ihrem Code.Sie könnten denken , die Sie verwenden können ,
Task.Yield()
statt, aber es stellt sich heraus , das ErgebnisTask.Yield()
ist nicht ein Subtyp vonTask
, während das ErgebnisTask.Delay(0)
ist. Das ist einer der subtilen Unterschiede zwischen den beiden.quelle
Sie können Task.FromResult (in .NET 4.5) verwenden, um ein abgeschlossenes Ergebnis zurückzugeben
Task<T>
.Wenn Sie eine nicht generische benötigen
Task
, können Sie immerTask.FromResult(0)
oder ähnlich verwenden, daTask<T>
es sich um eine Unterklasse von handeltTask
.quelle
Für .Net 4.6 und höher verwenden
Für niedrigere Version können Sie verwenden
quelle
return Task.Delay(0);
stattdessen zu verwenden?Sie können Nito.AsyncEx.TaskConstants.Completed aus einer großartigen Bibliothek AsyncEx von Stephen Cleary verwenden .
quelle
Wie wäre es mit:
Sie können die Warnunterdrückung weglassen, wenn Sie nichts dagegen haben.
quelle
async
immer noch der gesamte Zustandsmaschinenapparat erstellt wird, auch wenn Sie ihn nicht verwenden. Daher ist das Zurückgeben einer leeren Aufgabe für Szenarien mit geringen Ressourcen effizienter.