Wie machen die Aufgabe erwartbaren
Gestern habe ich angefangen zu spielen mit Microsoft CTP async Bibliothek und nirgends konnte ich nicht finden, die die ordnungsgemäße Durchführung des erwartbaren Aufgabe. Ich weiß, dass es muss die Umsetzung so?:
public struct SampleAwaiter<T>
{
private readonly Task<T> task;
public SampleAwaiter(Task<T> task) { this.task = task; }
public bool IsCompleted { get { return task.IsCompleted; } }
public void OnCompleted(Action continuation) { TaskEx.Run(continuation); }
public T GetResult() { return task.Result; }
}
Aber wie kann ich das nun umsetzen-eine Aufgabe, die würde, sagen wir mal, 5 Sekunden warten, und wieder einige Zeichenkette, z.B. "Hallo Welt"?
Einer Weg ist, um die Aufgabe direkt in etwa so:
Task<string> task = TaskEx.Run(
() =>
{
Thread.Sleep(5000);
return "Hello World";
});
string str = await task;
Aber wie würde ich das mit den erwartbaren Umsetzung? Oder habe ich es nur falsch verstanden alles?
Vielen Dank für jede information/Hilfe 🙂
- async/await gilt für die Methoden, nicht um Aufgaben.
await
gilt für Ausdrücke, die eine geeigneteGetAwaiter()
Umsetzung, dieTask
tut - soawait
gilt fürTask
(in einem Sinn)- In diesem schmalen Gehäuse, die Sie tun können
await TaskEx.Delay(5000);
, aber Sie haben für die Studie mehr für den Allgemeinen Fall. Dieawait
keyword suchtGetAwaiter
, und im Grunde alles, was einen geeignetenGetAwaiter
verwendet werden kann, mit erwarten. Jon Skeet ist eine tolle Serie in seinem blog disecting erwarten Sie in großem detail. - warten gilt nicht für die Methoden. Es gilt für beliebigen Ausdruck angeben, der Task oder Task(T). Dies ist ein häufiger Fehler.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der Schlüssel hier ist
AsyncCtpThreadingExtensions.GetAwaiter
bietet diese Methoden über eine extension-Methode. Da die async-Umsetzung ist Muster basiert (wie bei LINQ), anstatt an einen bestimmten Schnittstelle kann es von überall her (es istTaskAwaiter
in diesem Fall).Ihrem code, wie geschrieben ist erwartbaren. Zum Beispiel:
Diese Drucke
Hello World
nach 5 Sekunden.Neben der ein Jahr später
Nach der Verwendung von async-await für über ein Jahr jetzt, ich weiß, dass einige Dinge über async schrieb ich in meiner ursprünglichen Antwort nicht richtig, obwohl der code in der Antwort ist immer noch korrekt. Hera sind zwei links, die hat mir geholfen zu verstehen, wie die async-await funktioniert.
Dieses interview Eric Lippert zeigt eine ausgezeichnete Analogie für async-await. Suche irgendwo in der Mitte für async-await.
In diesem Artikel, der immer so hilfsbereit Eric Lippert zeigt einige gute Praktiken für async-await
Ursprüngliche Antwort
OK, hier ist ein vollständiges Beispiel, das mir half, während des Lernprozesses.
Angenommen, Sie haben einen langsamen Rechner, und Sie es verwenden möchten, die beim drücken einer Taste. Mittlerweile Sie wollen, dass Ihre Benutzeroberfläche zu bleiben, reagieren, und vielleicht auch andere Dinge tun. Wenn der Rechner fertig ist, die Sie wollen, um das Ergebnis anzuzeigen.
Und natürlich: verwenden async /await für diese, und keine der alten Methoden, wie das einstellen von Ereignis-flags warten und für diese Ereignisse festgelegt werden.
Hier ist der langsame Rechner:
Wenn Sie dies nutzen wollen, asynchron während der Verwendung von async-await verwenden Sie die Task.Laufen (...), um es zu starten asynchron. Der Rückgabewert von
Task.Run
ist ein erwartbaren Aufgabe:Task
wenn der return-Wert der Funktion, die Sie Ausführen, ist ungültigTask<TResult>
wenn der return-Wert der Funktion, die Sie ausführen istTResult
Können Sie einfach starten Sie die Aufgabe, etwas anderes zu tun, und Wann benötigen Sie das Ergebnis der Aufgabe geben Sie Sie erwarten. Einen Nachteil gibt es:
Wenn Sie wollen, 'erwarten' Ihre Funktion benötigt, um asynchrone und zurück
Task
stattvoid
oderTask<TResult>
stattTResult
.Hier ist der code, der ausgeführt die langsamen Rechner.
Es ist eine übliche Praxis zu beenden, die Bezeichner einer asynchronen Funktion mit async.
Den SlowAdd gestartet wird, da eine asynchrone Funktion, und deinen thread weiter. Einmal muss es die Antwort, die er erwartet für die Aufgabe. Der Rückgabewert ist die TResult, die in diesem Fall ein int.
Wenn Sie nichts sinnvolles zu tun, würde der code wie folgt Aussehen:
Beachten Sie, dass SlowAddAsync deklariert ist eine asynchrone Funktion, so dass jeder Benutzer dieses async-Funktion sollte auch async und zurückgeben Aufgabe oder Aufgabe
<TResult
>:Die nette Sache über async /await ist, dass Sie nicht haben, um Geige mit ContinueWith zu warten, bis der Vorherige task abgeschlossen ist. Verwenden Sie einfach warten, und Sie wissen, die Aufgabe ist fertig und Sie haben den Rückgabewert. Die Anweisung nach dem warten ist das, was man normalerweise nicht in der ContinueWith.
Durch die Art und Weise, Ihre Aufgabe.Führen Sie nicht haben, um eine Funktion aufzurufen, kannst du auch einen Anweisungsblock es:
Aber die nette Sache über eine separate Funktion ist, dass Sie diejenigen, die nicht brauchen /wollen /verstehen, async, die Möglichkeit der Verwendung der Funktion ohne async /await.
Denken Sie daran:
"Aber meine event-handler nicht mehr zurück können, eine Aufgabe!"
Du hast Recht, deshalb ist die einzige Ausnahme:
Also bei Klick auf die Schaltfläche, die der asynchronen event-handler halten würde, das UI responsive:
Aber Sie haben noch zu erklären, dass die event-handler async
Gibt es async-Funktionen für
- Internet-Zugang
- Stream Lesen und Schreiben
- Datenbank-Zugang
- etc.
Verwenden Sie Sie nicht haben, um Anruf-Aufgabe.Führen Sie bereits zurück Aufgabe
<TResult
> nennen Sie einfach, auch weiterhin tun, Ihre eigenen Sachen, und wenn Sie Sie brauchen, die Antwort erwarten für die Aufgabe und den nutzen der TResult.Beginnen mehrere Aufgaben aus und warten Sie, bis Sie fertig
Wenn Sie beginnen, mehrere Aufgaben und Sie wollen warten, bis Sie zu beenden, verwenden Sie den Task.WhenAll(...) NICHT Aufgabe.Warten
Aufgabe.Warten Sie einen void zurückgibt. Aufgabe.WhenAll gibt eine Aufgabe, so können Sie erwarten es.
Sobald eine Aufgabe abgeschlossen ist, wird der return-Wert ist bereits die Rückkehr von dem erwarten, aber wenn Sie erwarten Aufgabe.WhenAll ( neue Aufgabe[]{TaskA, TaskB, TaskC});
Sie haben die Aufgabe
<TResult
>.Result-Eigenschaft, um zu wissen, das Ergebnis einer Aufgabe:Wenn man die Aufgaben löst eine Ausnahme aus, ist verpackt wie InnerExceptions in eine AggregateException. Also, wenn Sie erwarten Aufgabe.WhenAll, bereit sein, zu fangen, die AggregateException und überprüfen Sie die innerExceptions, um zu sehen, alle Ausnahmen, die durch die Aufgaben, die Sie gestartet. Verwenden Sie die Funktion AggregateException.Flatten, um den Zugriff auf die Ausnahmen leichter.
Interessant zu Lesen über die Stornierung:
MSDN über den Abbruch in verwalteten threads
Schließlich: verwenden Sie Thread.Schlaf(...). Die async-version ist die Aufgabe.Delay(TimeSpan):
Wenn Sie mit dieser Funktion Ihr Programm hält reaktionsschnell.