Must I Invoke() to show dialog or MessageBox from a thread? Must I Invoke() to show dialog or MessageBox from a thread? multithreading multithreading

Must I Invoke() to show dialog or MessageBox from a thread?


It is a bit of a bug in Winforms. It contains diagnostic code in the Handle property getter that verifies that the property is used in the same thread as the one that created the handle. While extremely helpful to diagnose threading bugs, that is not always appropriate. One such case is here, Windows doesn't actually require that the parent of a window is owned by the same thread.

You can work around it by pinvoking SetParent() or by temporarily disabling checking with Control.CheckForIllegalCrossThreadCalls. Or by using Control.Invoke(), the best way. Do not work around it by not specifying the owner. For lack of another window, the dialog's owner is the desktop window. It will have no Z-order relationship with the other windows that have the desktop as their owner. And that will make the dialog disappear behind another window occasionally, completely undiscoverable by the user.

There's a bigger problem though, displaying dialogs on threads is a nasty usability problem. Shoving a window into the user's face while she's working with your program is an all-around bad idea. There's no telling what will happen when she's busy clicking and typing. Her accidentally closing the dialog without even seeing it is a real danger. Don't do it.


If you are not specifying the owner of the MessageBox it will work because it doesn't rely on the form UI thread.
I think it is safe to call it without using Invoke if you are not aware of showing as a dialog to specific form.

Edit: To test it, the following code just creating a new thread and show message box from it where at UI thread creating a second message at the same time with specifying the owner to be the form, both messages shows up without any problem:

private void button1_Click(object sender, EventArgs e){    new Thread(() =>    {        MessageBox.Show("Hello There!");    }) { IsBackground = true }.Start();    Thread.Sleep(1000);    if (MessageBox.Show(this, "Hi", "Jalal", MessageBoxButtons.YesNo) ==         System.Windows.Forms.DialogResult.Yes)    {        return;    }}


When I need to interact with some controls, created in main thread from another thread I use BackgroundWorker. It has event called OnProgressChange. So maeby try create this BackgroundWorker object in main thread, and in DoWork method just fire this event, then method attached to it will be executed in main thread, so you have access to all controls.