异步方法中的 C# 模态对话框(ShowDialog 或 MessageBox.Show)无法按预期工作

C# Modal dialog box (ShowDialog or MessageBox.Show) in async method not works as expected

我有一个最顶层的 WinForm,带有一个异步执行一些命令的简单按钮:

        private async void button1_Click(object sender, EventArgs e)
    {
        await System.Threading.Tasks.Task.Run(() =>
        {
            System.Threading.Thread.Sleep(2000);

            //Problem1: not works as "modal" dialog box (Main form remains active!) 
            new Form().ShowDialog();

            //Problem2: not shown as "modal" messagebox (Main form remains active!)
            MessageBox.Show("Test");
        });
    }

异步函数内部是 Messagebox.Show()ShowDialog() 方法,但是:

问题 1(已解决):新窗体未作为模态对话框打开(主窗体仍处于活动状态且可访问!)

问题 2(已解决): MessageBox.Show() 方法不作为模态对话框(主窗体仍处于活动状态且可访问!)。

我需要 async-await 来防止主 UI 冻结,但我也希望内部的消息框(和子表单)显示为模态对话框盒子。我如何通过异步方法显示模态对话框(在最顶层的主窗体上)?

谢谢

Task.Run() 在后台线程中运行工作。通常你不应该从后台线程显示 windows,但你可以。要解决您的问题,您需要使用 UI thread Dispatcher。

Application.Current.Dispatcher.Invoke(() => MessageBox.Show("Test"));

或者

Application.Current.Dispatcher.Invoke(() => new Form().ShowDialog());

问题 1 的解决方案: ShowDialogAsync扩展方法解决问题。

问题 2 的解决方案:

        private async void button1_Click(object sender, EventArgs e)
    {

        var handle = this.Handle;
        await System.Threading.Tasks.Task.Run(() =>
        {
            System.Threading.Thread.Sleep(2000);

            //Solution for Problem2:

            NativeWindow win32Parent = new NativeWindow();
            win32Parent.AssignHandle(handle);
            //Works as expected (Topmost and Modal):
            MessageBox.Show(win32Parent, "Test");
        });
    }

Related topic