Why background thread not exiting when form closes? - c#

As I understand it, if I set _myThread.isBackground = true then the thread should exit when the form is closed. Unfortunately I'm not finding that my thread is exiting. Here is what my code looks like:
private void MainForm_Load(object sender, EventArgs e)
{
// <snip>
daemon = new Daemon();
// <snip>
}
public Daemon()
{
// Start the main thread which will do most of the connection checking and work
_mainThread = new Thread(() => MainThread(this));
_mainThread.IsBackground = true;
_mainThread.Start();
}
/// <summary>
/// This is the work that the main thread does.
/// </summary>
private void MainThread(Daemon daemon)
{
while(true)
{
try
{
// Do things.
Thread.Sleep(2000); // Sleep for a bit to not hammer.
}
catch (Exception e)
{
Logger.Exception(e);
}
}
}
I thought that since the thread is started from the form that setting isBackground=true would force it to close on form exit.
Am I missing or misinterpreting something?

Strictly speaking that the thread is a background thread prevents it from keeping the process alive. The process will stick around for as long as there is at least one non-background thread running. The UI thread is a non-background thread, and by default in a winform application closing the main thread will result in that thread completing.
So now that we have all of this we can see that, often enough, closing the main form will "kill" background processes, but there are any number of things that can stop this.
The main thread ending doesn't necessarily mean the application will end, and the UI thread will terminate. One can adjust the behavior of the application to end under different criteria, or add code to run in Main after the application finishes running.
You can also create additional non-UI threads, and if you do, they'll keep the entire process (and all of the background threads) alive.

According to documentation background thread just wont prevent the process from terminating. There is no guarantee that the thread will finish "nicely", whatever that may mean.

IsBackground = true means that when main thread ended (and all other non-background threads) - it'll stop. But what are these threads ? I believe when you close your mainform you still have one non-background thread running may be one where this form was created and ititialized.

Related

How To create a foreground task?

I seem to fail to create a foreground task.
my main thread is supppose to call another thread and then exit.
the other thread suppose to run forever
void MainThreadMain()
{
task_main = Task.Factory.StartNew(() => OtherThread()) ;
return;
}
void OtherThread()
{
while(true)
{
TellChuckNorrisJoke();
}
}
how can I ensure task_main will continue running even that Main Thread is dead?
I assumed il do:
task_main.IsBackgorund = false;
but no such option :\
I can make my main thread to wait a signal from my other thread that it passed to Foreground mode. but thats plain silly.
The obvious question is: why don't you run your work on the main thread?
Assuming this is not an option, you should use a Thread not a Task. Then you can set:
Thread.IsBackground = false;
This will prevent your application from terminating while the worker thread is running.

What happens to the main thread in this case

I have the following multithreaded program:
class Program{
static void main(){
(new Thread(DoSomething)).Start();
}
static void DoSomething(){
// Dome something here...
}
}
A couple of questions:
Does the main thread exit after spinning off the child thread?
If it does exit and the child thread is a background thread: Is the main process going to exit or will it wait for the background thread to finish?
"By default, threads you create explicitly are foreground threads. Foreground threads keep the application alive for as long as any one of them is running, whereas background threads do not. Once all foreground threads finish, the application ends, and any background threads still running abruptly terminate.
class PriorityTest
{
static void Main (string[] args)
{
Thread worker = new Thread ( () => Console.ReadLine() );
if (args.Length > 0) worker.IsBackground = true;
worker.Start();
}
}
If this program is called without any arguments, the worker thread will take foreground status and will wait on the ReadLine statement for the user to press Enter. Simultaniously, the main thread exits, but the application keeps running because a foreground thread is still alive.
However, if an argument is passed to Main(), the worker is assigned background status, and the program exits almost immediately as the main thread ends (terminating the ReadLine and the program)."
See Joseph Albahri's (a genius and great guy) page on threading for more information (it is where this was extracted from).
Typically, if you want to wait for the child thread to complete, you'd add a x.Join(); line (where x is the variable of your thread) wherever you want your main thread to stop and wait for the child to complete.
EDIT: So, yes, the main thread will exit unless one of three cases occurs:
a) the spawned thread completes before the rest of the main thread code (if you add any)
b) You have a condition that waits for the thread to complete (such as the Join statement I mentioned, but there are other ways too).
c) The main thread goes into a semi-infinite loop (such as a game/graphics engine).
In your bare-bones example, it will exit for sure (given your question's parameters, a background thread).
EDIT2: Sorry, I seem to have dodged your second question (and actually only considered background threads the whole while). If it's a background thread it will exit as I've explained, if it's foreground then it shouldn't (though I don't have much experience with foreground threads, so I can't say for sure).
So to answer your questions: Yes, the main thread exits. Yes, if the child is specifically a background thread, the process will exit as well.
EDIT3: Final edit, I promise. I just wanted to add some code so that you could prove the answer yourself (which is always nice to be able to do):
static void Main(string[] args)
{
Thread thready = new Thread(DoSomething);
thready.IsBackground = true;
thready.Start();
}
static void DoSomething()
{
while (true)
{
Console.Write("thread's looping \n");
}
}
By toggling the thready.IsBackground = true; to thready.IsBackground = false; you get a program that runs forever (not exiting until the thread does). Leaving it as true will exit very quickly.
Depends on Thread.IsBackground.
The process will not exit before all the foreground threads finish. In the following example...
class Program {
static void Main(string[] args) {
(new Thread(DoSomething)).Start();
}
static void DoSomething() {
Thread.Sleep(5000);
}
}
...the process will exit after 5 seconds.
But in this example...
class Program {
static void Main(string[] args) {
(new Thread(DoSomething) { IsBackground = true }).Start();
}
static void DoSomething() {
Thread.Sleep(5000);
}
}
...the process will exit (almost) immediately. The effect on the child background thread that is still running is similar to forcibly killing the process, so avoid doing that if possible.
main process thread will definitely exit...
edit: i rechecked the docs and found that IsBackground property is false by default...which means the main thread will wait...the earlier response ws with regards to the 2nd question

Thread persists after application termination due to AutoResetEvent signal in WaitOne state

I have an application that uses an AutoResetEvent (WaitOne/Set) in a queue for processing messages. I'm noticing that when I terminate the a debug session from Visual Studio (Shift+F5) the original process for the application hangs around (but not always). I manually re-attach the debugger to the process, and see it has single thread stuck on WaitHandle.WaitOne.
So my question is, what is the correct way to terminate threads that may be in a WaitOne state?
The first answer that sprang to mind was listen to the Application Exit event and doing a Set there, but I wasn't sure if this event was called reliably after these debug sessions, or if there is a more standard practice that I am not aware of.
And, as a second question, would you handle this differently for the application running in 'production' mode?
There is a simple way to do this (not a workaround)
First, you need to set an event that will fire when your application is going to die
// somewhere with global scope. On a singleton or in program class maybe
// this is set when you want to terminate your application
private static ManualResetEvent ExitWaitHandle = new ManualResetEvent(false);
And this is how to use it elsewhere
// the event you want to check but it's blocking your application termination
private static AutoResetEvent yourEvent = new AutoResetEvent(true);
// the method where you have the problem
private static void FooAsync()
{
try
{
WaitHandle.WaitAny(new WaitHandle[]{yourEvent, ExitWaitHandle});
Checkpoint();
// other stuff here
// check if thread must die
Checkpoint();
}
catch(ApplicationTerminatingException)
{
// thread must die, do cleanup and finalization stuff here
}
catch(Exception)
{
// holy cow! what should we do?
}
}
private void CheckPoint()
{
// fast check if the exit handle is set
if(ExitWaitHandle.WaitOne(0))
{
throw new ApplicationTerminatingException(); // custom exception
}
}
The only overhead is that after "some" code you need to set a checkpoint in order to abort your thread. Hope this is what you were looking for.
One solution is to set the thread as background thread using the Thread.IsBackground property. When set on a thread that thread will not stop a process for exiting.
However, the thread may be interrupted at any time usually leading to undefined behavior depending on what your thread is doing. The best way to terminate a thread in my humble opinion is to signal the thread to exit, e.g. by setting a quit flag and set the WaitHandle and to wake it up then Joining the thread.

.NET C# Thread exception handling

I thought I understood this, and am a bit embarrassed to be asking, but, can someone explain to me why the breakpoint in the exception handler of following code is not hit?
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
Thread testThread = new Thread(new ParameterizedThreadStart(TestDownloadThread));
testThread.IsBackground = true;
testThread.Start();
}
static void TestDownloadThread(object parameters)
{
WebClient webClient = new WebClient();
try
{
webClient.DownloadFile("foo", "bar");
}
catch (Exception e)
{
System.Console.WriteLine("Error downloading: " + e.Message);
}
}
You're creating a thread, setting it to be a background thread, and starting it. Your "main" thread is then finishing. Because the new thread is a background thread, it doesn't keep the process alive - so the whole process is finishing before the background thread runs into any problems.
If you write:
testThread.Join();
in your Main method, or don't set the new thread to be a background thread, you should hit the breakpoint.
Your thread is a Background thread (you set it so yourself). This means that when the application completes, the thread will be shut down without being given chance to complete.
Because your main has no further content, it exits immediately and both the application and your thread are terminated.
If you were to add a testThread.Join() call then your thread would complete before the app exited and you'd see the exception caught.
Most likely your background thread isn't started before Main exits - starting a new thread may take a while. Since the additional thread is a background thread it is terminated when Main exits.
For demo purposes, you could have your main method wait - e.g. on user input. This would allow the background thread to start running.
Since the new thread's IsBackground is true, it won't prevent the process from terminating. At the end of Main() the only foreground thread terminates, shutting down the process before the other thread gets that far.
Probably because the main thread is ending before the worker thread. Try adding
Console.ReadKey();
at the end of your Main method.

How do I properly close a C# application that has created multiple threads?

I am writing a GUI application.
The application is opening multiple threads during it's life time. One of the threads is handling events that can come from other applications, so it is waiting in a while(true) loop for the event which is never been terminated.
The user can close the application in any minute. I want to close all the threads that the main application had opened.
I am using Process.GetCurrentProcess().Kill(); to deal with this problem at the moment.
Is this a good solution? If not, why and what is the proper way to deal with this problem, how to close all threads that were opened by the main application?
If you create the new threads as background threads (by setting IsBackground before starting them), they will automatically stop when the main thread (the application thread) terminates.
(From MSDN):
A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.
Once you already have threads waiting for some events, just add one more event that when triggered will instruct the thread to terminate.
In case you don't need to provide some means of graceful shutdown for other threads, you can switch them into the “background thread” mode to ensure automatic termination — see MSDN for a thorough discussion of this topic.
There are a lot of ways to deal with this, but ideally you want your threads to exit normally on their own rather than just killing the process.
You could do something very simple like this:
public class ThreadSignal
{
public bool Stop { get; set; }
}
Then in your thread loop, do:
public void DoWork(object state)
{
ThreadSignal signal = (ThreadSignal)state;
while(!signal.Stop)
{
// Do work here
}
}
Then when you're ready to stop, set your ThreadSignal.Stop to true. This is a very simple example, but it gives you a starting point.
You should wait in the loop with a ManualResetEvent (or AutoResetEvent).
Then just set a member variable to true when you are shutting down:
public class MyForm : Form
{
private AutoResetEvent _workTrigger = new AutoResetEvent();
private bool _shuttingDown = false;
private Thread _thread;
public void Form_Initialize()
{
_thread = new Thread(MyThreadMethod);
_thread.Start();
}
public static void MyThreadMethod(object State)
{
while (!_shuttingDown)
{
//wait for jobs.
_workTrigger.WaitOne(); //can add a timeout as parameter.
//do some work here
}
}
public void Form_Closing(object source, EventArgs e)
{
_shuttingDown = true;
_workTrigger.Set();
//wait for it to exit. You could use the timeout
//parameter and a loop to not block the UI
_thread.Join();
}
}
As you mentioned it's a GUI application so the main thread which is responsible for message loop is responsible for alerting the infinite (while(true)) loop that user wants to exit the program. I recommend to replace true with another boolean for signaling that user has closed the window like this: while(windowIsOpen) and set it to false on the unload of your form.
Don't lose your threads around the application - keep'em somewhere (List<Thread> will do fine). Then when the time is right (closing time) notify each one that it should finish what it's doing and exit.
Then, .Join() all of them, then allow application to exit.
Don't ever go to 'ThreadAbort' realm, it's dark side of the force that lurks there.
Generally how I do this is:
Create a Class that encapsulates this behavior (e.g. handling incoming messages in the background
Have the Class inherit from IDisposable. When Dispose() is called set a private variable named _disposed
Create my dedicated thread in my Class constructor.
Have a private AutoResetEvent named _workToDo. Your background thread will wait on this event and only do a work loop when this event is signaled.
Have a public method to send the message to your background worker that queues the work up and then sets _workToDo to tell your background thread to do the work.
Putting this all together, you get:
public class BackgroundProcessor : IDisposed
{
private Thread _backgroundThread;
private bool _disposed;
private AutoResetEvent _workToDo = new AutoResetEvent(false);
// where T is a class with the set of parameters for your background work
private Queue<T> _workQueue = Queue.Synchronized(new Queue<T>);
public BackgroundProcessor()
{
_backgroundThread = new Thread(DoBackgroundWork);
_backgroundThread.Start();
}
public void Dispose()
{
_disposed = true;
// Wait 5 seconds for the processing of any previously submitted work to finish.
// This gives you a clean exit. May want to check return value for timeout and log
// a warning if pending background work was not completed in time.
// If you're not sure what you want to do yet, a Debug.Assert is a great place to
// start because it will let you know if you do or don't go over time in general
// in your debug builds.
// Do *not* Join() and wait infinitely. This is a great way to introduce shutdown
// hangs into your app where your UI disappears but your process hangs around
// invisibly forever. Nasty problem to debug later...
Debug.Assert(_backgroundThread.Join(5000));
}
// Called by your 'other application'
public void GiveMeWorkToDo(T workParameters)
{
_workQueue.Enqueue(workParameters);
_workToDo.Set();
}
private void DoBackgroundWork()
{
while (!_disposed)
{
// 500 ms timeout to WaitOne allows your Dispose event to be detected if there is
// No work being submitted. This is a fancier version of a Thread.Sleep(500)
// loop. This is better because you will immediately start work when a new
// message is posted instead of waiting for the current Sleep statement to time
// out first.
_workToDo.WaitOne(500);
// It's possible multiple sets of work accumulated or that the previous loop picked up the work and there's none left. This is a thread safe way of handling this.
T workParamters = _workQueue.Count > 0 ? workParameters = _workQueue.Dequeue() : null;
do
{
DoSomething(workParameters);
workParameters = _workQueue.Count > 0 ? workParameters = _workQueue.Dequeue() : null;
} while (workParameters != null)
}
}
}
Consider using the BackGroundWorker class. Since it's using the threadpool (via BeginInvoke()), you'd get background threads. As a bonus you get convenient progress reporting, cancellation and completion callbacks (already marshalled to the UI thread).

Categories