How to kill Thread on exit? - c#

A button on the parent form is used to start the thread.
If the parent form is closed in the development environment the thread keeps running in the background preventing edits to the source code on a 64 bit Windows 7 platform.
The thread has to be killed by Menu > Debug > Stop Debugging.
What is the proper way to programmatically kill the thread when the parent Form is closed?
private void buttonW_Click(object sender, EventArgs e)
{
Thread t = new Thread(Main.MyThread);
t.Start();
}
private static void MyThread()
{
...
}

If you want the app to exit when the main thread has finished, you can just make the new thread a background thread:
Thread t = new Thread(Main.MyThread);
t.IsBackground = true;
t.Start();
Basically the process will exit when all the foreground threads have exited.
Note that this could be bad news if the background thread is writing a file when the form is closed, or something similar...

Environment.Exit(0) terminates this process and gives the underlying operating system the specified exit code. It is more generally used in console applications.
Environment.Exit(0);

Related

Waiting for Dispatcher.Invoke in WPF UI thread

I've got a BackgroundWorker that occasionally needs to call into the UI thread to perform some work and retrieve a result. To achieve this I'm using the following from within the background thread:
App.Current.Dispatcher.Invoke(new Action(() => { /* some code that updates local data */ });
As the app is exiting, I want to be able to tell the BackgroundWorker to quit but I want to allow it to finish any current operations. In other words, I want to call BackgroundWorkerObj.CancelAsync() and then pump messages until the thread has exited.
I've tried the following, but the Invoke() in the background thread still blocks (though the UI thread is still churning):
Worker.CancelAsync();
while (Worker.IsBusy)
{
DispatcherFrame Frame = new DispatcherFrame();
Frame.Continue = false;
Dispatcher.PushFrame(Frame);
}
What's the correct way to do this? How can the UI thread wait on the BackgroundWorker while still executing Invokes from that BackgroundWorker object?
This sort of shutdown deadlock is exactly why you shouldn't use Invoke for this purpose.
Change it to BeginInvoke(), and for communications back to the worker thread use an event.
I would use Task.Run since you're on .NET 4.0. but anyways. You have to do it the other way around. Wait for the backgroundworker to finish and then exit the application. There is no way to wait for the background thread to finish in an closing event while keeping the main thread responsive. This while loop will block the main thread and message pump until the background thread is done.
Try this
private BackgroundWorker _worker;
protected override OnFormClosing( object sender , FormClosingEventArgs e )
{
base.OnFormClosing( sender , e );
// Cancel's the closing and keeps the form alive
e.Cancel = _worker.IsBusy;
}
private void RunWorkerCompleted( object sender , RunWorkerCompletedEventArgs e)
{
// Work is done, so close the form
Close();
}

Join refuses to acknowledge that a child thread has terminated after the "IsAlive" property is false. C#

Nutshell: I launch a thread from my form, then some time later use the Join method on it. It terminates but my application is stuck on the Join and refuses to acknowledge that it's done joining. What would cause this to happen? My thread is launched from a button on my form, and attempts to join from a second button on the same form.
More Info:
I have an application that uses threading to accomplish communications and number crunching. Assuming the Main Form to be the parent thread, the first child is Child1. Upon starting Child1 establishes some communications with external devices and launches 2 child threads of its own (Child2 and Child3) to process the incoming data.
When the user decides that the application is to stop processing incoming data I need Child1 to terminate (so com settings can be altered prior to resuming, if necessary). I set a stop event and Child1 exits its execution loop, the first things it does is notify Child2 and Child3 that they are no longer needed (via another stop event), Child2 and Child3 are waited for with the Join method within Child1. This works just fine.
What does not work is that the form also uses the Join method on Child1 after setting the stop event that prompted Child1 to exit it's run loop and terminate, this Join, however, waits indefinitely.
Stepping Through: When I step through my app I notice that at the moment before using Join the IsAlive property is true. After I hit Child1.Join() I can no longer get any information from the thread because it's in "JoinWaitSleep". However, if I run a while loop that causes the form thread to sleep while Child1.IsAlive is true, this works just fine. Is my second button somehow part of a thread that cannot join Child1 to it?
public void Run()
{ //Known as Child1
//code to setup coms is here
//Launch Builder threads
InsertBackgroundMonitor("Launching Collector Threads");
RunBuilders = true;
//Known as Child2 and Child3
BuildThread1 = new Thread(new ThreadStart(Cam1Builder));
BuildThread2 = new Thread(new ThreadStart(Cam2Builder));
BuildThread1.Start();
BuildThread2.Start();
while (!StopEventHandle.WaitOne(0, true))
{
//// Code that waits for coms and tosses data into lists
}
RunBuilders = false;
//Wait for threads to terminate
BuildThread1.Join();
BuildThread2.Join();
}
private void RunButton_Click(object sender, System.EventArgs e)
{
//Button for running the control thread
ControlThread = new Thread(new ThreadStart(Run));
ControlThread.Start();
}
private void StopButton_Click(object sender, System.EventArgs e)
{
if (btnStop.Enabled)
{ //Button for stopping the control thread
StopEventHandle.Set();
if (ControlThread != null)
{
while (ControlThread.IsAlive)
{
Thread.Sleep(100);
}
//somehow Join did not work
//ControlThread.Join();
}
//Update buttons
btnStart.Enabled = true;
btnStop.Enabled = false;
}
}
It's difficult to say without more code, but you have SOME resource that you've started that you're not properly shutting down.
Join() waits for the thread to be completely shut down, and all resources released before returning. If the Thread has any BackgroundWorker tasks, or if it has any spare tasks that you aren't showing still running it will not return.
Since both of the BuildThread1 and BuildThread2 are returning correctly, and Join'ing, you can be sure it's not one of those, or anything that they're doing. Look over the rest of the code. What does it do?
EDIT:
This works fine:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread ControlThread;
Thread BuildThread1;
Thread BuildThread2;
volatile bool RunBuilders = true;
volatile bool RunControl = true;
private void button1_Click(object sender, EventArgs e)
{
ControlThread = new Thread(new ThreadStart(Run));
ControlThread.Start();
}
private void button2_Click(object sender, EventArgs e)
{
RunControl = false;
if (ControlThread != null)
{
while (ControlThread.IsAlive)
{
Thread.Sleep(100);
}
//somehow Join did not work
ControlThread.Join();
}
}
public void Run()
{ //Known as Child1
//code to setup coms is here
//Launch Builder threads
RunBuilders = true;
//Known as Child2 and Child3
BuildThread1 = new Thread(new ThreadStart(Cam1Builder));
BuildThread2 = new Thread(new ThreadStart(Cam1Builder));
BuildThread1.Start();
BuildThread2.Start();
while (RunControl)
{
//// Code that waits for coms and tosses data into lists
}
RunBuilders = false;
//Wait for threads to terminate
BuildThread1.Join();
BuildThread2.Join();
}
public void Cam1Builder()
{
while ( RunBuilders )
{
}
}
}
}
I can only guess at the possible issues that would cause this since I do not see the code for the Cam1Builder and Cam2Builder methods.1 The possibilities that immediately jump out at me are:
Calling Join blocks execution of the calling thread. If this is done from a UI thread then it stops the message pump. If the worker is trying to post messages to the UI thread (via Control.Invoke for example) then both threads will deadlock.
If RunBuilders is not marked as volatile or accessed inside a lock then its value, as perceived by other threads, cannot be predicted at any given point in time.
In general it is not advisable to call Join from the UI thread. UI threads are special in that they are running an indefinite loop which is dispatching and processing windows messages. This loop is initiated by calling Application.Run which you should see somewhere in your code. If you block the UI thread by calling Join or other blocking method then it cannot process queued messages. It is possible that you are using Control.Invoke to marshal the execution of a delegate on the UI thread from one of the worker threads. If this is the case then both threads will deadlock. Join blocks the UI thread waiting for the worker thread. Control.Invoke blocks the worker thread waiting for the UI thread.
Variables used as communication mechanisms between threads should be made thread-safe. In your case you are using RunBuilders as a mechanism for signaling an action on a worker thread. The problem is that since RunBuilders is neither marked as volatile nor accessed from within a lock block then its value cannot be reliably transferred to the worker thread. You may be setting its value to true in one thread, but another thread could continue to read false indefinitely.
1If you post more code I might be able to provide better insight. Specifically, I would like to see the general outline of what Cam1Builder or Cam2Builder is doing especially the parts where it is reading RunBuilders.
Did you try changing RunBuilders to volatile? Personally I don't know as I'd use a bool in this manner cross-threads, but if you're going to it should be volatile so all threads see the update instead of a stale value "cached" away by the JIT.
Other than that would need to see what the two other threads are doing.

How to exit all running threads?

The following code does not exit the application. How can I exit the application and make sure all the running threads are closed?
foreach (Form form in Application.OpenForms)
{
form.Close();
}
Application.Exit();
You don't show the use of any threads in your code, but let's suppose you do have threads in it. To close all your threads you should set all of them to background threads before you start them, then they will be closed automatically when the application exits, e.g.:
Thread myThread = new Thread(...);
myThread.IsBackground = true; // <-- Set your thread to background
myThread.Start(...);
A "HOWTO: Stop Multiple Threads" article from microsoft: http://msdn.microsoft.com/en-us/library/aa457093.aspx
You can try the following code:
Environment.Exit(Environment.ExitCode);
I went through a similar issue in my software, but unfortunately just making the threads to work in background didn't solve the issue. In fact while the thread brings back data (the main software is data driven) and if I close the application, it results to Windows Error, giving rise to a debugging message.
So what actually worked for me:
Step 1: Made all threads run in background such as
Thread aThread = new Thread(MethodName);
aThread.IsBackground = true; //<-- Set the thread to work in background
aThread.Start();
Step 2: In the closing action of the form/application call the Environment.Exit method, such as
Environment.Exit(Environment.ExitCode);
This kept the memory managed perfectly, with no memory leak.
Hope this helps.
This should work for all threads you opened.
protected override void OnExiting(Object sender, EventArgs args)
{
base.OnExiting(sender, args);
Environment.Exit(Environment.ExitCode);
}
This is the best way to make sure that your application closes (forcefully):
(Process.GetCurrentProcess()).Kill()
The problem with Environment.Exit is that it does not work unless it is on the main thread. Also, it sometimes thread locks.
The main reason that your program is not closing properly is because the form is not able to dispose itself (and thus all object that it created). Fixing this is much more difficult. I would recommend running the above code after waiting a while for any possible dispose handlers to get called first.
This got the job done for me:
Instead of using:
Application.Exit()
which leaves other threads open, try using:
Environment.Exit(Environment.ExitCode);
I puzzled with this for a while as the common answer is to make the threads you call mythread.IsBackground = true;
The common answer to run a thread is to use a while loop with a flag
while(!exitflag)
{
// thread running
}
When User presses the eXit forms button Visual studio still is running the threads but the form closes. I used the Form Closing event to set the exitcode flag and then wait for the threads to close.
I have a single form using a Timer and two additional threads, One collects streaming data and the other does calculations on that data and saves to an sql table. Data collection is collected in a circular buffer. I use two static bool values as flags where the threads set the flag to true or false using mythread.Isalive as the Form Closing event does not have access to the thread handles.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Debug.WriteLine("Form Closing Event");
exitFlag = true;
int ThreadsClosed = 0;
while (ThreadsClosed < 2)
{
ThreadsClosed = 2;
if (ProcessDataAlive) ThreadsClosed = 0;
if (StreamingDataAlive) ThreadsClosed = 0;
Application.DoEvents();
}
Debug.WriteLine("Threads are all closed");
Thread.Sleep(5000); // allow debug window open to read remove for release
}

How to know that I have another thread running apart from the main thread?

Suppose I have a routine like this:
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(Some_Work));
t.Start();
}
I need to put a condition so that, "If there is not already a thread running apart from the Main thread, start a new thread".
But how to test for whether a thread is running other than the Main thread?
There's several other threads running in your .NET app before it even gets to button1_Click. For instance, the finalizer thread is always hanging around, and I think WinForms creates one or two for itself.
Do you need to know about other threads that you've created? If so, you should keep track of them yourself. If not: why?
Edit: are you looking to kick off some background processing on demand? Have you seen the BackgroundWorker component, which manages threads for you, together with their interaction with the user interface? Or direct programming against the thread pool, using Delegate.BeginInvoke or ThreadPool.QueueUserWorkItem?
The easiest solution is of course to either store a reference to the existing thread, or just set a flag that you have a thread running.
You should also maintain that field (reference or flag) so that if the thread exits, it should unset that field so that the next "start request" starts a new one.
Easiest solution:
private volatile Thread _Thread;
...
if (_Thread == null)
{
_Thread = new Thread(new ThreadStart(Some_Work));
_Thread.Start();
}
private void Some_Work()
{
try
{
// your thread code here
}
finally
{
_Thread = null;
}
}

Does closing the application stops all active BackgroundWorkers?

Simple question, to repeat the title:
Does closing the WinForms application stops all active BackgroundWorkers?
Yes, it does.
BackgroundWorker.RunWorkerAsync simply calls BeginInvoke on a internal delegate, which in turn queues the request to the ThreadPool. Since all ThreadPool threads are background, yes, it will end when the application ends.
However, keep in mind that:
By "closing the WinForms application" I am presuming closing the main Form instance (that's generally the one passed to Application.Run in the Program class autogenerated by Visual Studio). If you have a child window with a background worker, it will not stop its BackgroundWorker automatically.
Letting a background thread be aborted on application exit is not the recommended way to end the thread, as you have no guarantees where it will be aborted. A much better way would be to signal the worker before closing, wait for it to finish gracefully, and then exit.
More info: Delegate.BeginInvoke, MSDN on Thread Pooling, Thread.IsBackground
The only way a thread can go on executing after your main (UI) thread has stopped is if it has been created explicitely, by creating a new Thread instance and setting the IsBackground to false. If you don't (or if you use the ThreadPool which spawns background threads - or the BackgroundWorker which also uses the ThreadPool internally) your thread will be a background thread and will be terminated when the main thread ends.
BackgroundWorker threads are background threads (ThreadPool threads), which die when the application dies.
Yes, it will. I wrote this simple form, and closing the form exits the application:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
Thread.Sleep(100);
}
}
}
If the application completely closes (as in nothing is preventing it from shutting down) your background workers will also be gone.
Once the process is gone all associated threads are gone as well.
First of all, just to make this answer simple:
When a process has closed, all of its threads have terminated. There's no question about this.
The question, as I interpret it, thus becomes:
Will still-running BackgroundWorker instances prevent an application from closing?
The answer to that question is: No, they won't.
I think yes. Because threads are associated with process and if the process is closed all threads has to end.

Categories

Resources