问题描述
我有一个最顶层的 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 冻结,但我也希望内部的消息框(和子表单)显示为模式对话框。如何通过异步方法显示模式对话框(在主要的最顶层表单上)?
谢谢
解决方法
问题 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");
});
}
,
Task.Run()
在后台线程中运行工作。通常,您不应该从后台线程显示窗口,但您可以。要解决您的问题,您需要使用 UI 线程 Dispatcher。
Application.Current.Dispatcher.Invoke(() => MessageBox.Show("Test"));
或
Application.Current.Dispatcher.Invoke(() => new Form().ShowDialog());