tags:

views:

89

answers:

5

I'm using the following method to show a modeless Message Box.

public void ShowMessageBox(string Message)
{
  var thread = new Thread(
    () =>
    {
      MessageBox.Show(Message);
    });
  thread.Start();
}

The "() => {...}" is something I've never seen before. What is the name for this code pattern?

Also, thread.Start starts the thread, and it automatically closes once the "()=>{...}" method completes (when the Message Box is OK'ed), right? If so, can you please point me to some official documentation saying that the thread closes automatically?

Thanks!

+7  A: 
STW
I believe `MessageBox.Show` is ok to call from any thread, but yes, it doesn't look good :-)
Mau
Can you please spin up some code showing how InvokeRequired and Invoke() can be implemented into my code? I am unfamiliar with these two things.
Soo
@Mau, my main objective is to create a thread that doesn't stop the code.
Soo
@Mau -- yes, MessageBox probably is already safe--but most UI work isn't, so I figured I should call it out.
STW
@Mau: correct, because it is each Window which is tied to the thread that created it. Different windows can belong to different threads (this has to be true, otherwise every Window on a desktop would have to be on the same thread, and thus in the same process).
Richard
@Soo it's not in C#, but you should be able to follow along with the old sample I provided: http://stackoverflow.com/questions/1110066/winforms-ui-responsiveness-when-dealing-with-heavy-data/1110126#1110126
STW
...and an article on `InvokeRequired` and `Invoke()` http://weblogs.asp.net/justin_rogers/pages/126345.aspx
STW
@richard: not sure youre right there...I think there is *one* window thread *per process*. Again, not sure.
Mau
@STV, I'm having a hard time understanding your code example (and don't have a whole lot of time). What are the dangers of running the code I have without the InvokeRequired and Invoke()?
Soo
@Soo -- give me a few minutes, I'll whip up a more concise example.
STW
Using Invoke in this instance would be the equivalent of just calling MessageBox.Show(), rather than having a thread call it. As far as threads and windows go, each Form's thread is the thread that created the form. Most of the time throughout an application this is just a single thread for all forms.
Alex Humphrey
@Alex Humphrey, if using Invoke is the same as calling MessageBox.Show(), does that mean using Invoke would stop the code while the Message Box is open?
Soo
@Soo - correct - Invoke is used when you want to get the UI thread for a Control to execute some code - the UI thread would show the modal dialog and block. Invoke is generally used when you want to update a Control from a thread that the Control was not created on, which is not your case. You launch another thread to create the message box, and show it.
Alex Humphrey
So using Invoke will prevent me from opening a modeless Message Box? Am I understanding this correctly? I'm mainly interested in making this Message Box modeless.
Soo
@Soo -- no, `InvokeRequired` and `Invoke()` are used to ensure the code that updates the UI is executed on the correct thread--the actual code that's executed could be anything--it's nothing Modal/Modeless specific. My sample has been added, you can replace the `textBox1.Text = value` statement with any UI updates you'd wish to do.
STW
@STW, can you please explain what blocking the UI means? I am very new to C# and don't know a lot about a lot.
Soo
@Soo -- "blocking" just means that the UI will not be updated until the code completes. Try adding a call to `Thread.Sleep(10000);` directly inside a button-click handler--when it's clicked the UI will freeze for 10-seconds because the UI Thread is 'blocked' by the Thread.Sleep(). Calling Thread.Sleep() on a background thread is non-blocking--the UI will remain responsive because the *background* thread is sleeping, the *UI* thread is free to process events immediately.
STW
@STW, if the UI thread isn't blocked by a background thread, would I be able to set thread.IsBackground = true and forget about using Invoke? (since Invoke minimizes the blockage, but if the thread is a background thread to begin with, it wouldn't need a blockage minimization because it doesn't block the UI thread?)
Soo
@Soo -- to clarify the rule to follow: background threads do not need to be concerned with `InvokeRequired` or `Invoke()` ***unless*** they modify the UI. UI modifications must be marshalled back to the UI Thread. If a method which modifies the UI is *ever* subject to be executed on a background thread then the `InvokeRequired` and `Invoke()` pattern should always be used for safety
STW
@Mau: any number of threads in a single process can create a Window. Each Window is tied to its creating thread, and each of those threads needs to run a message pump. For a UI it is unusual to do this, but where Windows are used non-visually it is quite common. E.g. running a COM STA on a thread you create needs a Window to process the messages the STA uses to ensure non-concurrent method dispatch.
Richard
+2  A: 

This is called a Lambda Expression. You can read more here.

Jake Pearson
+3  A: 

That is a Lambda. In this case, you're using it to create a new anonymous method that will be run when the new Thread is started.

It's the (near) equivalent of:

public void ShowMessageBox(string Message)
{
    var thread = new Thread(ShowBox);
    thread.Start(Message);
}

public void ShowBox(object message)
{
    MessageBox.Show(message.ToString());
}
Justin Niessner
+1  A: 

Its a statement lambda.

Yes, thread is active as long as this anonymous method is running. Since after MessageBox.Show() there is no other statements, thread will exit, and this must be true... if you are in doubt add this before start:

thread.Name = "LALALA";

And then debug your app. When the message box apear, pause execution, go to Threads View and you will see LALALA running. Click OK and pause again, there should be no "LALALA"... =)

Cipi
+2  A: 

Lambda expression, C# version 3 feature.

Don't use this code. A message box needs a parent window, something it can make sure to be on top of. It can normally find a parent by itself by iterating the windows that were created on the same thread. Not in this case though, there are no other windows, it has to pick the desktop window as the parent.

That will go wrong badly when the user is working in an app window or switches focus to another app, the message box disappears behind the foreground window. There is no obvious way for the user to tell that it is there, she'll just loses sight of it. It could be hours, if not days, before she finds it back. That thread is meanwhile consuming resources badly, you would probably never consider it if you knew that this message box requires a megabyte of memory. In extreme cases, you'll crash the program with OOM.

The common alternative in Windows UI programming is a balloon tooltip provided by a NotifyIcon. Or your own form with the TopMost property set to True so it cannot easily get lost. Also allows you to control the position, important for "non-modal" notifications that should not get in the way. Set that form's ShowWithoutActivation property to true in the form constructor so it doesn't steal the focus.

Hans Passant
Good point. I am pretty sure the OP got that idea from me in another question. That is one problem I had not considered.
Brian Gideon
@Brian, never too late to edit your answer :)
Hans Passant