2017-12-11 8 views
0

gegoogelt ich viel und für den Moment der einzige async Implementierung I (einschließlich MSDN-Website) zu finden ist folgende:Herstellung Asynchron-Methode richtig

public async void Foo() 
{ 
... 
await StreamReader.ReadAsync(); 
... 
} 

So in allen Fällen nutzen sie eine Methode, die bereits async ist . Und das brauche ich nicht.

Lassen Sie uns sagen, dass ich eine schwere Methode, die etwas tut:

public void DoSomthing() 
{ 
... 
} 

Und es gibt Verfahren, wo ich diese DoSomething nennen:

public void MajorMethod() 
{ 
    DoSomething(); 
} 

Ich möchte DoSomething ayncthonous und nennen es machen.

Die einzige Lösung, die ich die folgenden sehen sei:

public Task MajorMethod() 
{ 
    return Task.Run(()=>DoSomething()); 
} 

Aber ich habe einige Kommentare, dass es nicht wirklich die Asynchron ist. Wie kann ich DoSomething async machen?

+0

Es gibt nichts falsch mit der Verwendung von 'Task.Run()' –

+2

Dies kann Ihnen helfen: https://stackoverflow.com/a/18015586/4610605 –

Antwort

0

Wenn die MajorMethod hat keine anderen Dinge zu tun als die DoSomething aufrufen, ist Ihr Code in Ordnung. Aber wenn Sie brauchen andere Sachen zu tun, nachdem DoSomething zu nennen, dann markieren Sie MajorMethod als async, und verwenden Sie await vor Task.Run

public async Task MajorMethod() 
{ 
    await Task.Run(()=>DoSomething()); 

    //stuff in here will executed after DoSomething completed 
} 

Beispiele aus MSDN: Asynchronous programming

oder nur google c# async

+5

Auch wenn ich nicht sagen würde dies ist ein No-op verglichen mit Bei der bestehenden Implementierung des OP sind die Unterschiede ziemlich subtil - und normalerweise würde ich stattdessen den OP-Code empfehlen. Was ist Ihrer Meinung nach der Vorteil, eine Aufgabe zu starten und dann asynchron darauf zu warten, anstatt die gestartete Aufgabe direkt zurückzugeben? –

+0

@JonSkeet Sie haben Recht. Ich verstehe das Bedürfnis von OP nicht. Wurde davon ausgegangen, dass eine Aktion ausgeführt wird, nachdem das 'DoSomething' in' MajorMethod' aufgerufen wurde. Es ist nicht notwendig, 'await' zu verwenden, wenn' MajorMethod' direkt nach dem Aufruf zurückgegeben wird –

0

Sie sollte klar sein, über die Rolle async/warten auf das Spiel in der Task Asynchronous Pattern. Das Erstellen einer asynchronen Methode entspricht einer Operation nicht einfach asynchron. Das Markieren einer existierenden Methode async führt nicht alles magisch asynchron durch. Sein Haupteffekt ist, dass Sie nun await innerhalb der Methode verwenden dürfen (ich habe gelesen, dass es sogar diskutiert wurde, ob das Schlüsselwort async überhaupt notwendig war; es wurde hinzugefügt, um eine brechende Änderung zu vermeiden, wenn eine lokale Variable in existierenden Methoden benannt würde await).

await bietet auch keine asynchrone selbst, es bietet eine Möglichkeit, mit einer anderen asynchronen Methode und Ausbeute zu synchronisieren, während der andere Vorgang noch ausgeführt wird. Sie können await eine andere async Methode, aber wenn nicht irgendwo in der Kette gibt es eine tatsächliche Task läuft in einem anderen Thread, könnte die asynchrone Methode sogar synchron zurückkehren.

Folglich bedeutet dies, dass Sie eine Operation benötigen, die asynchron erste (wie eine DB-Abfrage, Dateizugriff, Netzwerkkommunikation) läuft und von dort aus einer Kette von async Methoden erzeugen, die die bisherige Methode await.

Wenn Sie in einem Fall eine rechenintensive Methode haben, die nicht auf externe Ressourcen wartet, können Sie die Operation asynchron ausführen. Da moderne CPUs in der Regel mehr als einen Kern zur Verfügung haben, können Sie sowohl die Leistung als auch die Reaktionsfähigkeit der Anwendung erhöhen.Das Verfahren wäre nicht async, da er nichts erwarten:

void DoSomething() 
{ 
    //... 
} 

Task DoSomethingAsync() { 
    return Task.Run(DoSomething); 
} 

alle Anrufer von DoSomethingAsync jetzt await mit diesem Vorgang läuft im Hintergrund (beachten Sie die Änderung im Gegenzug Typ Task synchronisieren können Anrufer zu ermöglichen, erwarten):

async Task MajorMethod() { 
    //... 
    await DoSomethingAsync(); 
    //... 
} 

Diese Anrufer von MajorMethod mit ihm zu synchronisieren zulassen würde. Was Sie auch tun, ist Sachen in MajorMethod zu tun, während DoSomethingAsync läuft (und warten noch auf Anrufer zu ermöglichen, noch mehr parallele Operationen zu tun):

async Task MajorMethod() { 
    //This part will run before DoSomethingAsync 
    //... 
    Task doSomethingTask = DoSomethingAsync(); 
    //This part is executed at the same time as DoSomethingAsync 
    //... 
    await doSomethingTask; //Here the caller can do more operations while DoSomething is running 
    //This part will be executed after DoSomethingAsync has finished 
    //... 
} 

Diese Form einer Aufgabe zu erwerben, etwas zu tun, und nur dann wartet Die Aufgabe muss irgendwo in der Kette getan werden, sonst haben Sie keinen Vorteil von der asynchronen Operation. Auch wenn dies eine Übergeneralisierung sein könnte, da die Synchronisierung auf subtilere Weise erfolgen kann, z. B. mit einem benutzerdefinierten Synchronisationskontext. Aber was Ihre Frage betrifft, sollten Sie gehen mit: Es gibt eine tatsächliche Aufgabe an einem Ende und etwas, das nach dem asynchronen Anruf gemacht wird, aber vor dem Warten auf das andere Ende.