Reputation: 889
I've noticed that there seems to be inconsistent behavior as to when a MessageBox is modal.
First up, launching a MessageBox from the UI thread. This results in a modal MessageBox, as expected :
void MainThreadClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello!");
}
Next up, launching from a background thread. This results in a Modeless MessageBox, I assume because it's not on the UI thread?
void WorkerThreadClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((x) =>
{
MessageBox.Show("Hello!");
});
}
Next, launching from a background thread, but dispatched to the UI thread, results in it being modal again :
void WorkerThreadClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((x) =>
{
Application.Current.Dispatcher.Invoke(() =>
{
MessageBox.Show("Hello!");
});
});
}
And finally, this is the strange one, similar to above, but using the FileSystemWatcher thread results in a Modeless dialog. Why is this? ... it's being Invoked on the UI thread, so why isn't it Modal like the previous example?
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!");
});
}
Whilst I can solve the last problem using the MessagBox.Show() method that takes a Window owner as a parameter, I want to understand what's going on.
Why is the behavior different in the last 2 examples?
Upvotes: 5
Views: 1430
Reputation: 3004
This question has indeed stumped me for some time. On doing some analysis I found that in the last case (FileSystemWatcher
) the owner changed(I have not yet figured who has taken over the ownership).
I also found that there is a minor but important difference.
In the scenario number 2
void WorkerThreadClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem((x) =>
{
MessageBox.Show("Hello!");
});
}
Even though the behaviour is Modeless when ever I close my MainWindow
my application is also shut down.
In the FileSystemWatcher
scenario the behaviour is again Modeless but when I close my MainWindow
the application is not shut down unless I close the MessageBox
(so I know that someone has taken over the ownership. Who has taken it I don't know yet).
EDIT
I changed the Shutdown
mode in the last scenario
void OnFileSystemResourceChanged(object sender, FileSystemEventArgs args)
{
Application.Current.Dispatcher.Invoke(() =>
{
Application.Current.ShutdownMode=ShutdownMode.OnMainWindowClose;
MessageBox.Show("Test");
});
}
Even then when I close the MainWindow
my Application
is not closed unless the MessageBox
is closed. I tried finding the owner but then I get null reference exceptions.
Upvotes: 2