Ich glaube, dass die TPL (TaskFactory.Startnew) ähnlich wie ThreadPool.QueueUserWorkItem funktioniert, da sie die Arbeit an einem Thread im Thread-Pool in die Warteschlange stellt.
So ziemlich .
Nach dem, was ich gelesen habe, scheint es, als würde async / wait nur "manchmal" einen neuen Thread erstellen.
Eigentlich tut es das nie. Wenn Sie Multithreading möchten, müssen Sie es selbst implementieren. Es gibt eine neue Task.RunMethode, die nur eine Abkürzung ist Task.Factory.StartNew, und sie ist wahrscheinlich die häufigste Methode, um eine Aufgabe im Thread-Pool zu starten.
Wenn Sie sich mit E / A-Abschlussports befassen, kann ich sehen, dass kein neuer Thread erstellt werden muss, aber ansonsten würde ich denken, dass dies erforderlich ist.
Bingo. Methoden wie Stream.ReadAsyncerstellen also tatsächlich einen TaskWrapper um ein IOCP (wenn dasStream einen IOCP hat).
Sie können auch einige Nicht-E / A- und Nicht-CPU- "Aufgaben" erstellen. Ein einfaches Beispiel ist Task.Delay, dass eine Aufgabe zurückgegeben wird, die nach einiger Zeit abgeschlossen ist.
Das Coole an async/ awaitist, dass Sie einige Arbeiten in den Thread-Pool einreihen können (z. B. Task.Run), eine E / A-gebundene Operation ausführen (z. B. Stream.ReadAsync) und eine andere Operation ausführen können (z. B. Task.Delay) ... und sie sind alle Aufgaben! Sie können erwartet oder in Kombinationen wie verwendet werden Task.WhenAll.
Jede Methode, die zurückgibt, Taskkann awaitbearbeitet werden - es muss keine asyncMethode sein. So Task.Delayund I / O-gebundene Operationen verwenden nur TaskCompletionSourcezu erstellen und zu einer Aufgabe - das einzige , was auf dem Thread - Pool durchgeführt wird , ist der eigentliche Aufgabe Abschluss , wenn das Ereignis eintritt (Timeout, I / O - Abschluss, usw.).
Ich denke, mein Verständnis von FromCurrentSynchronizationContext war auch immer ein bisschen verschwommen. Ich habe immer gesagt, dass es im Wesentlichen der UI-Thread war.
Ich habe einen Artikel über geschrieben SynchronizationContext. Meistens SynchronizationContext.Current:
- ist ein UI-Kontext, wenn der aktuelle Thread ein UI-Thread ist.
- ist ein ASP.NET-Anforderungskontext, wenn der aktuelle Thread eine ASP.NET-Anforderung bearbeitet.
- ist sonst ein Thread-Pool-Kontext.
Jeder Thread kann seinen eigenen Thread festlegen SynchronizationContext, daher gibt es Ausnahmen zu den oben genannten Regeln.
Beachten Sie, dass der Standard- TaskKellner den Rest der asyncMethode für die aktuelle Methode plant, SynchronizationContext wenn sie nicht null ist . sonst geht es auf den Strom TaskScheduler. Dies ist heute nicht so wichtig, aber in naher Zukunft wird es eine wichtige Unterscheidung sein.
Ich habe mein eigenes async/ awaitIntro in meinem Blog geschrieben und Stephen Toub hat kürzlich eine exzellente async/ awaitFAQ gepostet .
Informationen zu "Parallelität" und "Multithreading" finden Sie in dieser verwandten SO-Frage . Ich würde sagen, asyncaktiviert Parallelität, die Multithreading sein kann oder nicht. Es ist einfach zu verwenden await Task.WhenAlloder await Task.WhenAnygleichzeitig zu verarbeiten. Wenn Sie den Thread-Pool nicht explizit verwenden (z. B. Task.Runoder ConfigureAwait(false)), können mehrere gleichzeitige Vorgänge gleichzeitig ausgeführt werden (z. B. mehrere E / A oder andere Arten wie Delay). und es wird kein Thread für sie benötigt. Ich verwende den Begriff "Single-Threaded-Parallelität" für diese Art von Szenario, obwohl in einem ASP.NET-Host tatsächlich " Null- Threaded-Parallelität" auftreten kann. Welches ist ziemlich süß.