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

Daniel Peñalba picture Daniel Peñalba · Aug 9, 2011 · Viewed 8.8k times · Source

I'm executing a code in a worker thread. Sometimes, I need to show a dialog or a Message.

I have been playing with the code and only seems to be strictly necesary to Invoke when I pass a IWin32Window to the dialog. Otherwise works fine.

My questions are two:

  1. Must I call with an Invoke?
  2. What risks I have if I show the dialog or the messagebox without Invoke?

Thanks in advance

Answer

Hans Passant picture Hans Passant · Aug 9, 2011

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.