Long-delayed update
I'm accepting MUG4N's answer to this question, and I also want to respond to some of the criticisms that were raised against it.
ChrisF said:
...you can't make UI calls directly from background threads.
This is a blanket statement, and is not 100% true. Let me just point out a few facts:
You can actually make UI calls all you want if you set
Control.CheckForIllegalCrossThreadCalls = false
. "Ack!" I hear you saying. "Don't ever do that!" Yes, yes -- but why? The answer: because sometimes this will corrupt memory.The control classes in
System.Windows.Forms
are not written to be thread-safe, so sometimes updating them from background threads can corrupt memory. But if this only sometimes happens and not always, what this tells me is that it is not the calling of UI code per se, but rather the potentially unsafe collision of UI code that can cause exceptions.To reinforce point 1, consider this: the "safe" way to invoke UI code from a background thread is to do so using
Control.Invoke
orControl.BeginInvoke
, right? But this is a UI call; it's just the UI call we're supposed to make if we're updating the GUI from a non-GUI thread. What I mean is, clearly, it is not simply invoking "any" method on aControl
object from an outside thread that's going to cause chaos (if that were the case, then we couldn't even callInvoke
and we'd be stuck completely). Again, it's the potential collision of separate UI calls that cannot safely occur simultaneously that will prove destructive.Keeping the above two points in mind, ask yourself: why would it be unsafe to call
MessageBox.Show
from a non-GUI thread? A completely separateForm
is created and displayed; its properties do not in any way interact with any other existing GUI object; in fact, it cannot be accessed anywhere in any manner, except for one: from the calling thread, which accesses itsDialogResult
property (and only that via theShow
method's return value).
Moving along. Conrad Albrecht said:
...given the assertion that Show() sets up its own message pump in Dan's ref'd topic, (which was not substantiated, but which I can't refute)...
This is a totally fair point (though I personally hold Jared Par in high enough esteem that I wouldn't generally be inclined to doubt what he says). In any case, a peek at the MessageBox.Show
method through Reflector reveals this snippet:
Application.BeginModalMessageLoop();
try
{
result = Win32ToDialogResult(SafeNativeMethods.MessageBox(new HandleRef(owner, zero), text, caption, type));
}
finally
{
Application.EndModalMessageLoop();
UnsafeNativeMethods.ThemingScope.Deactivate(userCookie);
}
A further peek into the Application.BeginModalMessageLoop
method reveals this:
ThreadContext.FromCurrent().BeginModalMessageLoop(null);
And this ThreadContext.FromCurrent
, in turn:
// [Reflector shows that currentThreadContext is a ThreadStatic member. -Dan]
if (currentThreadContext == null)
{
currentThreadContext = new Application.ThreadContext();
}
return currentThreadContext;
I don't know enough about these lower-level Windows constructs to fully understand this code, but this seems to me to be evidence of exactly what Jared was saying in the answer I referenced in my old comment (for curious readers: Does MessageBox.Show() automatically marshall to the UI Thread?).
So, yeah. I am totally in agreement with MUG4N on this one.
(If anyone can convincingly argue that I am still mistaken here, please speak up. Although I feel I've made a pretty good case for why I believe MUG4N is right, I'm obviously not 100% certain.)
Original question
Often you just want to notify the user that something has occurred, but there's really no need for any input from them. In this common scenario, I sometimes see code like this:
MessageBox.Show("Something has occurred", "Something", MessageBoxButtons.OK);
This code, as we all know, causes a little pop-up window to appear with only an OK button. Now here's the thing: this code blocks (the UI thread). But in the vast majority of cases, it seems to me, if you only have an OK button, there's very little need to block. (Isn't the purpose of blocking typically to receive some input from the user? And if the user's only choice is "OK," in this typical case, isn't blocking pretty pointless?)
Obviously I could just write my own little form that does basically exactly what MessageBox.Show
does, except that it returns nothing (no DialogResult
) and doesn't block. But I was just wondering if something like this exists already that I didn't know about.