web-dev-qa-db-de.com

Erstellen Sie eine abgeschlossene Aufgabe

Ich möchte ein fertiges Task erstellen (nicht Task<T>). Gibt es etwas in .NET eingebaut, um dies zu tun?

Eine verwandte Frage: Erstelle eine erledigte Aufgabe <T>

173
Timothy Shields

Die neueste Version von .Net (v4.6) fügt genau das hinzu, ein eingebautes Task.CompletedTask :

Task completedTask = Task.CompletedTask;

Diese Eigenschaft ist als No-Lock-Singleton implementiert, sodass Sie fast immer dieselbe abgeschlossene Aufgabe verwenden würden.

219
i3arnon

Task<T> Ist implizit in Task konvertierbar. Holen Sie sich also einfach einen vollständigen Task<T> (Mit einem beliebigen T und einem beliebigen Wert) und verwenden Sie diesen. Sie können so etwas verwenden, um die Tatsache zu verbergen, dass irgendwo ein tatsächliches Ergebnis vorliegt.

private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
    return completedTask;
}

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 kein FromResult haben, können Sie mit TaskCompletionSource ein eigenes erstellen:

public static Task<T> FromResult<T>(T value)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(value);
    return tcs.Task;
}
144
Servy

Meine bevorzugte Methode hierfür ist der Aufruf von Task.WhenAll() ohne Argumente. In MSDN-Dokumentation heißt es: "Wenn das bereitgestellte Array/enumerable keine Aufgaben enthält, wechselt die zurückgegebene Aufgabe sofort in einen RanToCompletion-Status, bevor sie an den Aufrufer zurückgegeben wird." Das hört sich nach dem an, was Sie wollen.

Update: Ich fand die Quelle um Microsoft's Reference Source ; Dort sehen Sie, dass Task.WhenAll Folgendes enthält:

return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
            Task.CompletedTask :
            new WhenAllPromise(tasks);

Task.CompletedTask ist also zwar intern, wird jedoch durch Aufrufen von WhenAll () ohne Argumente verfügbar gemacht.

63
Richiban

Ich würde Task.Delay(0) verwenden. Intern gibt es eine zwischengespeicherte Instanz eines abgeschlossenen Task<T> Zurück. Dies ist genau das, was die aktuelle Antwort sowieso vorschlägt, nur müssen Sie jetzt weder eine Instanz selbst zwischenspeichern, noch haben Sie in Ihrem Code unelegante Garbage-Werte.

Sie könnten denken, Sie könnten stattdessen Task.Yield() verwenden, aber es stellt sich heraus, dass Task.Yield()nicht ein Subtyp von Task ist, wohingegen Das Ergebnis von Task.Delay(0) ist. Das ist einer der subtilen Unterschiede zwischen den beiden.

33
gzak

Sie können Task.FromResult (in .NET 4.5) verwenden, um einen vollständigen Task<T> Zurückzugeben.

Wenn Sie ein nicht generisches Task benötigen, können Sie immer Task.FromResult(0) oder ähnliches verwenden, da Task<T> Eine Unterklasse von Task ist.

29
Reed Copsey

Für .Net 4.6 und höher

return Task.CompletedTask;

Für niedrigere Versionen können Sie verwenden

return new Task(() => { });
8
Icen

Sie können Nito.AsyncEx.TaskConstants.Completed aus einer großartigen Bibliothek AsyncEx aus Stephen Cleary verwenden.

8

Wie wäre es mit:

#pragma warning disable 1998
    public async Task emptyTask() {
    }
#pragma warning restore 1998

Sie können die Warnungsunterdrückung auslassen, wenn Sie nichts dagegen haben.

0
Dorus