异步方法中的 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
我有一个最顶层的 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