2013-06-28 66 views
0

預期的結果將是:創建在一個異步任務控制導致死鎖

SomeTask MainAsync 主要

class Program 
{ 
    static void Main(string[] args) 
    { 
     MainAsync().Wait(); 
     Console.WriteLine("Main"); 
     Console.ReadLine(); 
    } 

    async static Task MainAsync() 
    { 
     await Task.Run(() => SomeTask()); 
     Console.WriteLine("MainAsync"); 
    } 

    static async Task SomeTask() 
    { 
     TextBox tb = new TextBox(); 
     await Task.Delay(100); 
     Console.WriteLine("SomeTask"); 
    } 
} 

然而,沒有Console.WriteLine命令的其實都是調用。

即使我編寫一個Windows窗體應用程序,它確實有一個win32消息循環也會發生同樣的事情。

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    protected async override void OnLoad(EventArgs e) 
    { 
     await MainAsync(); 
     MessageBox.Show("Done!"); 
     base.OnLoad(e); 
    } 

    async static Task MainAsync() 
    { 
     await Task.Run(() => SomeTask()); 

    static async Task SomeTask() 
    { 
     TextBox tb = new TextBox(); 
     await Task.Delay(100); 
    } 
} 

MessageBox從不出現。

+1

有人猜測,創建一個控件會創建一個同步上下文,但沒有一個活動的消息循環;這意味着它永遠不會處理來自同步上下文的消息;同步上下文是...棘手的 –

回答

1

Marc是正確的;現代Windows窗體控件將在創建時在其當前線程上建立WinForms SynchronizationContext

因此,SomeTask將安排它的延續到Win32消息循環,但是沒有線程處理該消息循環(例如,Application.Run)。

+0

更新的代碼呢?它顯然有一個win32消息循環,爲什麼它不起作用? – user2533483

+0

您仍在*另一個*(非UI)線程上創建控件,該線程沒有Win32消息循環。 –