2014-04-27 57 views
1

我有下面的代碼示例:異步方法在C#:延續點

using System; 
using System.Threading; 
using System.Threading.Tasks; 

namespace asynctest { 
    class Program { 
     public static void Main (string[] args) { 
      var program = new Program(); 
      program.run(); 
     } 

     public Program() { 
     } 

     public void run() { 
      asynctest(); 
      Console.WriteLine ("Sync"); 
      while (true) { 
      } 
     } 

     public async Task asynctest() { 
      await Task.Delay (100); 
      Console.WriteLine ("Async"); 
     } 
    } 
} 

當開始這個節目,我所期望的輸出只是「同步」,因爲asynctest法永遠不會在繼續我碼。

而是輸出「同步」和「異步」。

我現在的問題是程序從run方法切換到asynctest方法以打印「異步」行。從我以前的協程經驗來看,這不應該發生。從控制檯程序啓動

+3

它永遠不會從'run'切換到'asynctest'。另一個線程在'Task.Delay'後執行代碼(即繼續)。在這種情況下'ThreadPool'線程 –

回答

1

任務由默認的線程池運行,所以你的程序開始對線程A上運行你的asynctest方法被調用,一旦遇到await Task.Delay (100);返回,然後繼續寫出來的Sync字符串。然後在while循環中線程A塊。

編譯器從asynctest方法中構建一個狀態機,該方法在Task.Delay(100)結束時恢復執行線程池線程B並打印Async。然後線程B終止。線程A仍然卡在while循環中。

如果你把這種從UI線程,你會得到一個僵局由於await將嘗試執行的asynctest方法在UI線程上,這反過來又被擋在while(true)循環的剩餘部分。

看看this article,它解釋了更多關於asyncawait最佳做法。

+0

爲什麼在線程A上使用(B)和執行沒有被調度的新線程?那是因爲它忙於做「while循環」嗎? – brumScouse

+0

當您在線程池「SynchrinizationContext」上調用'await'時,可以在線程池中的任何線程上執行延續。我猜如果線程A可用,實現可以選擇安排剩餘的方法或任何其他可用線程。我認爲這是實施細節。有[方法](http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx)在完全相同的線程上執行,但是會遇到死鎖 –

+0

這聽起來很合理,所以我認爲這是正確的,直到有人證明它是錯誤的。謝謝您的回答。 – Richard