在异步任务中创建控件会导致死锁

时间:2013-06-28 22:13:00

标签: c# asynchronous controls deadlock async-await

预期结果将是:

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 个答案:

答案 0 :(得分:1)

马克是对的;现代Windows窗体控件将在创建时在其当前线程上建立WinForms SynchronizationContext

因此,SomeTask会将其继续调度到Win32消息循环,但是没有线程处理该消息循环(例如,Application.Run)。