views:

125

answers:

6

I'm writing a bit of code that will open a MessageBox on a separate thread to prevent the MessageBox from stopping the program. It is very very important that starting a new thread will not crash the program that I am running, but I don't know enough about threads to make sure this happens.

My question is, after starting the thread, how can I safely dispose of it after the MessageBox closes? I imagine closing/disposing of it is necessary so it's not just floating around after it is created and started.

Please advise, thanks!

var Thread = new Thread
(
    ()=>
    {
        MessageBox.Show("Buy pizza, Pay with snakes");
    }
);
Thread.Start();
+6  A: 

You don't need to do anything special.

Thread instances are automatically "cleaned up" (rather they become candidates for garbage collection) when there's no references to them (in your code) and their main method body has terminated. In fact, Thread doesn't implement IDisposable - so speaking of it's "disposal" is incorrect.

In your example, once the lambda method completes (ie the message box is closed), the thread will automatically terminate. You don't need to do anything extra.

Now there's a difference between reclaiming allocated memory and having objects become candidates for disposal/collection. Any objects allocated will remain on the GC heap until the next collection cleans them up ... but you shouldn't have to care about that.

A separate issue you may need to contend with is performing UI operations on a thread other than the main UI thread. While it is possible, you have to be careful not to reference any UI elements that are created on a different thread from the one you create.

LBushkin
+2  A: 

A Thread will automatically clean itself up once the code contained within it completes. You don't have to manually dispose of it (and, in fact, it's not IDisposable!).

Reed Copsey
So the code I have in my OP doesn't carry any risk of failing? The reliability of this component is extremely important.
Soo
@Soo: Any code has some risk of failing, but no, in general, the code you have above is fairly safe. I typically use a different approach (I'd make a custom Form, and display it using Form.Show() instead of Form.ShowDialog()) for various reasons - including not requiring a full thread stack to be allocated, but the above should work.
Reed Copsey
@Reed: I actually started building a separate form and realized it would be more difficult to implement it into a bigger program as it would require adding a whole form item added (and this other bigger program doesn't need any clutter), while the messagebox is basically just built in. I do appreciate the suggestion though thanks :)
Soo
@Soo: You can make a single "NonModalMessageForm" usable throughout your application. Using a separate thread has a major disadvantage - the thread allocates a fairly large amount of memory for its private stack, which will get cleaned, but can eat up time and spike memory for no good reason.
Reed Copsey
@Reed: Are all forms nonmodal and made modal by using ShowDialog(); instead of Show();?
Soo
@Soo: Yes. ShowDialog() shows a form modally, and Show() does not. It's very easy to make a custom "MessageBox" form that you can show modally or non-modally, plus, you get the advantage of allowing for extra style in the form, if you want. (I did a non-modal MessageBox implementation for my program in about 15 minutes - there's almost nothing to it, since it's basically a label + icon + OK/Cancel button).
Reed Copsey
@Reed: I do agree that your solution of using a form is more effective (at least in terms of styling, I'm not so familiar with the technical performance advantages but don't doubt them either). I will chat with my boss to see if it's ok to add an additional form item to the existing project.
Soo
@Soo: Just to be fair - there is one disadvantage to my approach. If you are doing a long processing job *on the UI thread*, it will prevent the user from closing the form, since the UI thread will be blocked, and messages can't be processed. That being said, I try to always push the long running work onto background threads, and leave all UI on the UI thread, so it's not normally an issue. I just mention it because it does have slightly different behavior than your above approach (I feel it's better, still, but...)
Reed Copsey
@Reed, I do agree with you, it all comes down to what my boss wants. Thanks for the additional comments, I recognize and appreciate the effort you put into helping people on this site.
Soo
+2  A: 

The thread will close automatically after the scope of the lambda expression is left... in your case you don't need to worry about anything.

In general it's also good practice to set the thread to background, because if your application is closed you might get a message box just hanging out there by itself:

var thread = new Thread(
    ()=>
    {
        MessageBox.Show("Buy pizza, pay with snakes");
    });
thread.IsBackground = true;
thread.Start();

Note: it's preferred that your variables start with a lower letter. For details on naming conventions please see the Microsoft Naming Guidelines.

Lirik
@Lirik: Regarding your note, I don't mean to be a jackass, I just need clarification for these things as I am a noob. Now, Public = capitalized, Private = uncapitalized. Is "thread" considered private, requiring the undercase first letter or is there another reason for it to be uncapitalized?
Soo
@Soo, no insult meant and none was taken... just trying to help :). I just mentioned it because it makes it easier for anybody looking at your code to understand what's going on: normally the capitalized Thread is used to access static properties and methods of the Thread class, naming your variable the same as the class type is confusing (although not syntactically incorrect). In general public and private members are with lower case letters, but properties and methods are capitalized.
Lirik
@Lirik, Thanks for that clarification. I starred this thread so I can come back to your comment when unsure about capitalization rules.
Soo
offtopic: where does the "Buy pizza, pay with snakes" line come from? Must be another meme, uh?!
tobsen
@tobsen: Google Image Search: "Advice Dog". I love animals, so the humor strikes a chord with me.
Soo
A: 

A few things first...

  1. Threads don't "crash" the program unless an unhandled exception is thrown from within it.
  2. You don't need to dispose of a thread. Finishing its main routine is enough.
  3. If necessary, you can make your program wait for the end of the thread execution using the Join() method on your Thread instance.

And then a suggestion: it seems that you need a modeless MessageBox. AFAIK, the feasible way of doing this is creating a custom form and display it through Show() instead of ShowDialog().

Humberto
A: 

In C#, you shouldn't have to care all that much once the thread goes out of scope. It's a simple answer, but simple is good: let the computer do what it's good at. :-)

Ed Ropple
A: 

You should be aware that if an exception is thrown by your worker thread and is not caught, then your application may abort (as Humberto mentioned in point #1). The example you provided is trivial, and I can't imagine that it would throw an exception, but you may want to consider at least wrapping the worker thread logic in a try/catch.

I would suggest not using a separate thread for this purpose. Create your own form for displaying the message and show it with the Show method. Creating a form like this isn't too difficult; I recommend making use of the Button.DialogResult, Form.AcceptButton, and Form.CancelButton properties. You have more control over the appearance of the form

In terms of reliability, an advantage of keeping your code out of a worker thread is that you can subscribe to the Application.ThreadException event in order to handle any exceptions that were not caught by your application's logic. This allows you to prevent your application from crashing due to an unhandled exception, but be aware that this will affect your entire application.

Dr. Wily's Apprentice