views:

266

answers:

5

I have an application which does some background task (network listening & reading) in separate Thread. It seems however that the Thread is not being Terminated/Aborted when I close the application (click "x" button on titlebar ;)). Is that because the main Thread routine is while(true) {...} ? What is the solution here? I was looking for some "interruption" flag for the Thread as the condition for "while" loop, but didn't found any ...

+7  A: 

The simplest way is to set the IsBackground property of the thread to true. This will prevent it from keeping the application open. An application terminates when all non-background threads terminate.

A more controlled way to stop the thread is to send it a message to shut down cleanly and ensure that it has terminated before letting your main thread terminate.

A method that I wouldn't recommend is to call Thread.Abort. This has a number of problems, one of which is that it is not guaranteed to terminate the thread. From the documentation:

Calling this method usually terminates the thread.

Emphasis mine.

Mark Byers
+1 to the message method. `while (stayAlive)` instead of `true` is much cleaner, even if it potentially takes a few extra seconds for the loop to clear up.
sixlettervariables
A: 

Well, instead of while(true), maybe you should:

while(appIsRunning)
{
}

And, at the closing event for your form,

appIsRunning = false;
thread.Join(2000);

where the last line is just to make sure you wait for the thread to cleanly finish. There are many other ways to force an end to a thread, but the problem is just there: you don't want to be forcing things, you want them to happen as naturally as possible.

After the join, you can check the status of thread to see if it has finished. If it doesn't, then (and only then) force its finish with a abort, and maybe notify your user (or write a log record) that something has not ended the way it should.

Bruno Brant
Yes, but do remember to use `volatile` or `lock` or some other method of synchronization.
Mark Byers
@Mark: might be totally wrong here, but since the child Thread only reads and the main Thread only writes, is there a chance for a bug?
Bruno Brant
@Bruno Brant: Without synchronizing it is not guaranteed that a change to appIsRunning from one thread will be visible in the other thread. You can read more here: http://timl.net/2009/03/volatile-memory.html
Mark Byers
+1  A: 

You could improve the while(true) loop to

void DoWork() {
    while(!ShouldIQuitManualResetEvent.WaitOne(0)) {
      // do something
    }
    IDidQuitManualResetEvent.Set()
}

A bit more graceful, short from the identifier names.

Hans Passant
A: 

You can always force the issue:

class Program
{
    public static void Main()
    {
        // ... do stuff
        Environment.Exit(Environment.ExitCode);
    }
}

The better approach is to set the Thread.IsBackground property to true as Mark already mentioned.

csharptest.net
A: 

You can start your thread as:

ThreadPool.QueueUserWorkItem(DoStuff, input)

And it will be abort automatically with application close.

darja