wforl
wforl

Reputation: 889

Modal Messagebox from background thread

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

Answers (1)

Sandesh
Sandesh

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

Related Questions