Question

How can I force ShowDialog to return from a background thread?

I have a WPF application built on top of a C++/CLR framework which is listening to messages sent by the framework. One particular message is so important that I need to close all the current windows. However, if a modal Dialog (created by ShowDialog from my main window) is active and awaiting user input, the window will not close because it is waiting for ShowDialog to return. How can I force the modal Dialog to close and unwind code execution?

I tried setting the DialogResult or calling Close however that doesn't seem to work.

Edit: The Dialog is created by my main window which expects a return value, like so: (inside a click event handler in MainWindow):

Window modalDialog = new Window();
bool ret = (bool)modalDialog.ShowDialog();
if (ret == true)
{
 // do stuff
}
else
{
 // do some other stuff
}

When the framework sends a message (coming in on a different thread than the UI thread), I call MainWindow.Close(). The modal dialog gets closed at this point, however the code checking the return value of the Dialog (after ShowDialog) is still on the stack. Somehow this forces the main window to not disappear.

Was it helpful?

Solution

When the dialog receives the WM_CLOSE message it sets a flag that causes ShowDialog to return after the WM_CLOSE and any containing messages have been fully processed. So if you are doing a Dispatcher.Invoke() onto your thread to call MainWindow.Close(), the ShowDialog() won't return until after the Dispatcher.Invoke() has completed.

So the simple solution is to return from the Dispatcher.Invoke() to get the ShowDialog() to return. If more processing is required, do another Dispatcher.Invoke() immediately afterwards.

If you are doing the thread transition some other way than Dispatcher.Invoke(), or if the ShowDialog() doesn't return after the Dispatcher.Invoke() call returns, you may have to post some of the code surrounding your Window.Close() call so we can see what you are actually doing.

OTHER TIPS

You can't force ShowDialog to return but you can have the window listen to an event sent by your framework that can tell it to close. In the example below Progress event has a "Done" flag the closes the window when done.

SomeGenerator IG = Manager.SomeGenerator();
SomeWindow PP = new SomeWindow();
IG.ProgressEvent += PP.ProgressEvent;
IG.ExecuteAsync();            
PP.ShowDialog();

I realize now that I cannot force ShowDialog to return and continue execution whenever I want it to. The event handler for the request that I receive from the framework needs go out of context so the call stack can be unwound and the modal dialog can process the Close message.

I ended up setting a boolean flag, requesting the modals to close, then return from my framework event handler. Only at this point will ShowDialog return and I can check for the flag I set and continue with the requested action.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top