2013-10-31 24 views
1

我目前通過深入閱讀C#(第三版),並給出的警告之一是使用GUI線程與task.wait是危險的,因爲它可能導致僵局。但是它不是ThreadPool或Console的問題。我的問題是爲什麼運行task.wait的線程不會死鎖,因此對於下面的代碼(從書中獲取),即使是控制檯應用程序(backround)線程也不會使它捕捉到捕捉,因爲它會死鎖。GUI task.wait vs控制檯或ThreadPool的死鎖

public static void Main(string[] args = null) 
{ 
     var source = new CancellationTokenSource(); 
     var task = TestInt(source.Token); 
     source.CancelAfter(4000); 
     Console.WriteLine("Status {0}",task.Status); 
     try 
     { 
      task.Wait(); 
     } 
     catch (AggregateException e) 
     { 
      Console.WriteLine("Caught {0}",e.InnerExceptions[0]); 
     } 
     Console.WriteLine("Final Status: {0}",task.Status); 
     Console.ReadKey(); 
    } 

    public static async Task TestInt(CancellationToken token, double start = 1) 
    { 

     await Task.Delay(TimeSpan.FromSeconds(30), token); 
    } 

感謝您

+1

我已經解釋它[這裏](http://stackoverflow.com/a/19543729/2530848) –

回答

5

我詳細in a blog post解釋。

會發生什麼情況是(默認情況下)await將捕獲當前的「上下文」並使用該上下文來恢復執行方法async。這個「上下文」是SynchronizationContext.Current,除非它是null,在這種情況下它是TaskScheduler.Current

在你的例子中,SynchronizationContext.CurrentnullTaskScheduler.CurrentTaskScheduler.Default,也就是線程池任務調度程序。因此,async方法在線程池線程上恢復並且沒有死鎖。線程池線程完成async方法,完成Task,允許主線程完成其等待。

(在死鎖情況下,有表示在UI線程一個SynchronizationContext,所以async方法試圖恢復在UI線程上但UI線程通過調用Wait阻止)。

+0

感謝您的答案和鏈接到您的博客,這似乎有很多的線程和同步帖子。 –