我注意到,当MessageBox是模态的时,似乎存在不一致的行为。
首先,从UI线程启动MessageBox。这会产生一个模态MessageBox,如预期的那样:
void MainThreadClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello!");
}
接下来,从后台线程启动。这会产生一个无模式MessageBox,我假设因为它不在UI线程上?
void WorkerThreadClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((x) =>
{
MessageBox.Show("Hello!");
});
}
接下来,从后台线程启动,但调度到UI线程,导致它再次成为模态:
void WorkerThreadClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((x) =>
{
Application.Current.Dispatcher.Invoke(() =>
{
MessageBox.Show("Hello!");
});
});
}
最后,这是一个奇怪的,与上面类似,但使用FileSystemWatcher线程会产生一个无模式对话框。为什么是这样? ...它是在UI线程上调用的,那么为什么它不像上一个示例那样是模态?
public MainWindow()
{
InitializeComponent();
m_watcher = new FileSystemWatcher()
{
Path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
NotifyFilter = NotifyFilters.LastWrite,
IncludeSubdirectories = true,
Filter = "*.*"
};
m_watcher.Changed += OnFileSystemResourceChanged;
m_watcher.EnableRaisingEvents = true;
}
void OnFileSystemResourceChanged(object _sender, FileSystemEventArgs _args)
{
Application.Current.Dispatcher.Invoke(() =>
{
MessageBox.Show("Hello!");
});
}
虽然我可以使用将Window所有者作为参数的MessagBox.Show()方法解决最后一个问题,但我想了解发生了什么。
为什么最后两个例子中的行为有所不同?
答案 0 :(得分:1)
这个问题确实困扰了我一段时间。在进行一些分析时,我发现在最后一种情况下(FileSystemWatcher
)所有者发生了变化(我还没有想到谁接管了所有权)。
我还发现有一个小但重要的区别。
在场景编号2中
void WorkerThreadClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((x) =>
{
MessageBox.Show("Hello!");
});
}
即使行为是无模式的,但是当我关闭MainWindow
时,我的应用程序也会关闭。
在FileSystemWatcher
方案中,行为再次成为无模式,但当我关闭MainWindow
时,应用程序不会关闭,除非我关闭MessageBox
(所以我知道有人接管了所有权。谁拿走了我还不知道。)
修改强>
我在最后一个场景中更改了Shutdown
模式
void OnFileSystemResourceChanged(object sender, FileSystemEventArgs args)
{
Application.Current.Dispatcher.Invoke(() =>
{
Application.Current.ShutdownMode=ShutdownMode.OnMainWindowClose;
MessageBox.Show("Test");
});
}
即使这样,当我关闭MainWindow
我的Application
时,除非MessageBox
关闭,否则{{1}}未关闭。我尝试找到所有者,但后来我得到了空引用异常。