Instead of showing the dialog in the current thread, create a new thread and set it's apartment level to single-threaded apartment. Have the current thread start this thread and then join to it until it returns. The second thread will then call the ShowDialog method of the WinForm. Because this occurs in a separate thread it will create it's own message pump. When ShowDialog returns, set a variable to the DialogResult value and return. When the current thread starts up again it can read the DialogResult and return it. Following is the C# code I used to workaround this problem in our own solutions:
Code: Select all
private volatile static Form dialog;
private volatile static DialogResult dialogResult;
public static DialogResult SafeShowDialog(Form dialog) {
if(dialog == null) {
return DialogResult.Cancel;
}
Common.dialog = dialog;
Thread t = new Thread(new ThreadStart(SafeShowDialogThreadProc));
t.ApartmentState = ApartmentState.STA;
t.IsBackground = false;
t.Start();
t.Join();
return dialogResult;
}
private static void SafeShowDialogThreadProc() {
try {
dialogResult = dialog.ShowDialog(OwnerForm);
}
catch(Exception ex) {
dialogResult = DialogResult.Cancel;
Application.OnThreadException(ex);
}
}