6

Ich bin in letzter Zeit ziemlich viele Situationen gestoßen, wo async Methoden synchron ausführen, aber eine Aufgabe trotzdem zurückgeben, so dass sie erwartet werden können, z.Task.FromResult() vs Task.Run()

public virtual Task CreateAsync(TUser user) 
{ 
    ThrowIfDisposed(); 
    if (user == null) throw new ArgumentNullException("user"); 
    Context.Save(user); 
    Context.Flush(); 
    return Task.FromResult(0); 
} 

Sicherlich ist es besser, die wahrscheinlich lange laufende Betrieb zu einem Faden und gibt die noch aktive Aufgabe zu entsenden, um wirklich abgewartet werden:

public virtual Task CreateAsync(TUser user) 
{ 
    ThrowIfDisposed(); 
    if (user == null) throw new ArgumentNullException("user"); 
    return Task.Run(() => 
    { 
     Context.Save(user); 
     Context.Flush(); 
    }); 
} 

ich einigen Verdacht aber, dass nur Das Abspulen von TPL-Threads ist nicht die sicherste Vorgehensweise. Irgendwelche Kommentare zu diesen zwei verschiedenen Mustern?

+0

Wenn möglich, sollten Sie eine tatsächliche Async-Methode anstelle von beiden aufrufen. – SLaks

+0

@SLaks Auf welche Weise ist der zweite nicht asynchron (außer dass kein neues Schlüsselwort verwendet wird)? (kommt von jemandem, der häufig keine Async-Funktionen verwendet) –

+0

@KyleW: Es verschwendet immer noch einen Thread. Siehe http://blog.slaks.net/2014-12-23/parallelism-async-threading-explained/ – SLaks

Antwort

10

Wenn Ihre Methode synchron ist, sollten Sie zunächst keine Task zurückgeben. Erstellen Sie einfach eine traditionelle synchrone Methode.

Wenn aus irgendeinem Grunde nicht möglich ist (zum Beispiel Sie einig Asynchron-Schnittstelle implementieren), um eine erledigte Aufgabe Rückkehr Task.FromResult oder sogar besser in diesem Fall Task.CompletedTask (hinzugefügt in .NET 4.6) ist viel besser als Task.Run bei der Umsetzung mit :

public virtual Task CreateAsync(TUser user) 
{ 
    // ... 
    return Task.CompletedTask; 
} 

Wenn der Verbraucher Ihrer API läuft stark über die Task -returning Methode nicht synchron kümmert sie Task.Run sich verwenden, um sicherzustellen.

Sie sollten bedenken, dass asynchrone Methoden einen beträchtlichen synchronen Teil haben können (der Teil vor dem ersten Warten), selbst wenn sie schließlich asynchron fortfahren. Sie können nicht annehmen, dass asynchrone Methoden sofort eine Task zurückgeben.

5

Task.FromResult erstellt nicht tatsächlich oder führt eine Aufgabe aus, sondern umschließt das zurückgegebene Ergebnis in einem Aufgabenobjekt. Ich persönlich benutze es in Unit Tests, wo ich die Async Methoden simulieren muss und natürlich würde ich keine tatsächlichen Aufgaben in Unit-Tests ausführen wollen.

Außerdem wird Task.Run tatsächlich eine Aufgabe erstellen und eine Aufgabe auf TaskScheduler ausführen. Es wird nicht empfohlen, Task.Run zu verwenden, wenn Sie Async programmieren. Verwenden Sie stattdessen await für Aufgaben. Siehe einige do's and don't of Tasks von Stephen Cleary.

Verwandte Themen