views:

103

answers:

5

Pseudo-situation: have a class (let's say BackgroundMagic), and it has Start() and Stop() methods. The work in this class is done by one single thread, and is simply a short loop every X milliseconds.

Which of these options is better, as far as managing the stopping/starting? Can't decide which road to take.

  1. The first time Start() is called, initialize and start the thread with IsBackground = true. Use a simple bool flag to indicate on each loop around whether it should actually do any work, or just sleep. After initial initialization, let Stop() and Start() simply control the bool flag. The thread will just be stopped and cleaned up by the runtime since IsBackground = true when the app exits.
  2. Forcefully abort/join/interrupt/whatever on Stop, and recreate the thread again on Start(), not leaving the thread lying around.

... or any better/cleaner ways of doing this?

A: 

Thread creation is fairly expensive, so the standard "industrial-strength" way to do this is to control the thread with a flag. For a larger-scale variant on the same idea, consider the thread pools that e.g. Apache uses to manage thousands of threads without a lot of explicit state or a painful performance hit.

So in the abstract, I'd vote for your option #1. But if performance isn't a concern and the option #2 code is easier to reason about, go for it.

David Seiler
+7  A: 

Neither! Use a Thread Pool!

Dave Markle
A: 

You can also use a bool flag to indicate if the thread should stop. Which gives you your interrupt and stop code. So two bools one for if there is work and one to stop the loop.

The other thing you could consider is using the Dispose pattern and cleaning up the thread when the object is disposed.

Glenn Condron
A: 

I would use the bool flag, but you need to be sure it is either correctly locked or only set from one thread. Your loop should look like this

while (true)
{
  if (shouldSleep)
 {
   Thread.Sleep(interval);
   continue;
 }

  doSomeWork();

 if (shouldCancel)
 {
   CleanUpResources();
   break;
 }
}

This makes sure you can send the thread to sleep but also correctly terminate it. Killing a thread is never a good idea if you can avoid it as the thread doesn't have a chance to clean up any resources used. You need to decide on an appropriate sleep interval though. It will determine the latency your thread needs to start up.

The second option is rather expensive, thread creation involves some OS resources and startup time is also considerable. If thread recreation won't happen often and the amount of work performed is large enough this would be reasonable. You can avoid the complexity involved in the loop approach.

Johannes Rudolph
A: 

A mutex or semaphore would be a better option than a simple boolean flag, because it doesn't require checking the state of the flag repeatedly. Simply block on the mutex/semaphore, and when you want the thread to run, release the mutex/semaphore and the thread will run once.

qid