2016-11-17 156 views
-5

我編寫了一個程序來檢查我是否理解異步等待概念。異步並等待線程問題

 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); 
    } 

我有點迷惑,會有什麼打印?

我認爲我們不能保證什麼都會打印

我Explantion: 當await DoAsyncWork是調用控件回到主菜單。在DoAsyncWork之後 完成控制返回並在等待之後繼續代碼的其餘部分。 其餘的代碼可以運行,我們沒有關於巫婆線程運行此代碼的保證。

其實: 我運行這段代碼很多時間,並得到False打印。

+4

你打算問同樣的問題多少次? http://stackoverflow.com/questions/40577858/async-await-thread-expected – Jim

+0

*我們沒有關於巫婆線程運行此代碼的保證。*如果'await'將安排繼續而不是繼續(因爲它會做會看到已經完成的任務),那麼我們保證繼續將在'ThreadPool'線程之一運行。和以前一樣,它不使用ThreadPool線程,它保證線程不同。 – PetSerAl

+1

你真的應該停止反覆詢問同一個問題。更好地閱讀這篇文章,而不是:http://blog.stephencleary.com/2012/02/async-and-await.html – VMAtm

回答

4

await將使用SynchronizationContext.Current來確定如何執行延續代碼。如果當前同步上下文中有一個值,並且同步上下文的特定實現最終會運行在特定線程上發送給它的所有代碼,那麼您將始終最終在同一線程中運行代碼。 (WinForms或WPF應用程序設置的同步上下文會執行此操作)。

如果沒有同步上下文(在您的代碼中就是這種情況),將使用默認值,它使用線程池,因此它最終可能會在任何線程上運行。也可能有一個同步上下文集合,它不一定會在同一個線程上運行發送給它的所有代碼。 (ASP應用程序使用的同步上下文會執行此操作。)

由於在您的代碼中沒有同步上下文,因此將使用線程池,並且線程永遠不會相同。如果你創建了一個具有同步上下文的消息循環(比如說,當啓動一個winforms或WPF應用程序時會發生這種情況)並且從中調用Run2,那麼這些線程就會可靠地匹配。

+0

因此,如果上下文在await關鍵字之前和之後是相同的,那麼這些線程將會是相同的? – maz

+0

@maz如果'await'之前沒有默認的上下文,那麼它就是在那個線程和上下文繼續被調用的上下文之前,假設'await'有一些東西需要等待並且沒有完成任務,在這種情況下執行將在當前線程中繼續。 – PetSerAl

+0

@PetSerAl你可以給考試,假設上下文是asp上下文嗎? – maz