2016-11-17 5 views
-5

Ich schreibe ein Programm, um zu überprüfen, ob ich das async-Warte-Konzept verstehe.async und warten Thread-Problem

 static void Main(string[] args) 
    { 
     Run2().Wait(); 
    } 

    static async Task DoAsyncWork() 
    { 
     await Task.Delay(2000); 
    } 

    static async Task Run2() 
    { 
     var tid = Thread.CurrentThread.ManagedThreadId; 
     await DoAsyncWork(); 
     Console.WriteLine(tid == Thread.CurrentThread.ManagedThreadId); 
    } 

Ich bin ein bisschen verwirrt, was wird gedruckt werden?

Ich denke, dass wir keine Garantie haben, was

Mein explantion drucken wird: Wenn await DoAsyncWork nennen, ist die Steuerung zurück zum Haupt. nach DoAsyncWork vervollständigen Sie die Kontrolle zurück und den Rest des Codes nach warten. Der Rest des Codes kann ausgeführt werden und wir haben keine Garantie dafür, dass dieser Thread ausgeführt wird.

Eigentlich: Ich führe diesen Code eine Menge Zeit und erhalten False drucken.

+4

Wie oft werden Sie die gleiche Frage stellen? http://StackOverflow.com/Questions/40577858/async-wait-thread-expected – Jim

+0

* Wir haben keine Garantie über Hexe Thread führen Sie diesen Code. * Wenn 'erwarten' wird Fortsetzung planen statt nur weiter (wie es tun wird, wenn würde die bereits abgeschlossene Aufgabe sehen), dann haben wir die Garantie, dass die Fortsetzung auf einem von 'ThreadPool'-Threads ausgeführt wird. Wie vorher 'erwarten' es nicht' ThreadPool'-Thread, dann garantiert es, dass Thread anders wäre. – PetSerAl

+1

Sie sollten wirklich aufhören, die gleiche Frage immer wieder zu stellen. Besser lesen Sie diesen Artikel stattdessen: http://blog.stephencleary.com/2012/02/async-and-await.html – VMAtm

Antwort

4

Die await wird SynchronizationContext.Current verwenden, um zu ermitteln, wie der Fortsetzungscode ausgeführt wird. Wenn im aktuellen Synchronisierungskontext ein Wert vorhanden ist und die jeweilige Implementierung des Synchronisierungskontexts den gesamten Code ausführt, der an einen bestimmten Thread gesendet wurde, wird der Code immer im selben Thread ausgeführt. (Der Synchronisierungskontext, den Winforms oder WPF-Anwendungen setzen, würde dies tun.)

Wenn kein Synchronisationskontext vorhanden ist (was in Ihrem Code der Fall ist), wird der Standardwert verwendet, der den Thread-Pool verwendet könnte am Ende auf jedem Thread laufen. Es ist auch möglich, dass es einen Synchronisationskontextsatz gibt, der nicht notwendigerweise den gesamten Code ausführt, der an denselben Thread gesendet wird. (Der Synchronisierungskontext, den eine ASP-Anwendung verwendet, würde dies tun.)

Da in Ihrem Code kein Synchronisierungskontext vorhanden ist, wird der Thread-Pool verwendet, und die Threads werden niemals dieselben sein. Wenn Sie eine Nachrichtenschleife erstellt haben, die über einen Synchronisierungskontext verfügt, der Nachrichten an sie weiterleitet (z. B. beim Starten einer Winforms- oder WPF-Anwendung) und Run2 heißt, würden die Threads zuverlässig übereinstimmen.

+0

Also, wenn der Kontext vor und nach dem erwarten Schlüsselwort gleich ist, so dass die Threads gleich sein werden? – maz

+0

@maz Wenn Sie vor 'warten' keinen Standardkontext haben, liegt es an diesem Kontext, in dem die Thread- und Kontextfortsetzung aufgerufen wird, vorausgesetzt, dass 'warten' auf etwas warten muss und nicht bereits abgeschlossene Aufgabe, in diesem Fall Die Ausführung wird im aktuellen Thread fortgesetzt. – PetSerAl

+0

@PetSerAl können Sie Beispiel geben, davon ausgehen, dass der Kontext asp Kontext ist? – maz