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

本文关键字:死锁 控件 创建 异步 任务 | 更新日期: 2023-09-27 18:20:16

预期结果为:

SomeTaskMainAsync主

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从未出现。

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

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

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