views:

67

answers:

3

I have a c# console application which has some threads to do some work (download a file). each thread may exit the application at any time any where in application, but I'll show a proper message on console. It's possible to track them but it doesn't make sense to me. I want simply check thread count or something like that to find out which one is the last thread and do something when it is exiting. What's the best practice to do so ?

pseudo code:

if (lastThread)
{
   cleanUp();
   Console.ReadLine();
}

Thanks

+1  A: 

Your main thread should join with all your worker threads and block while they are running. Then when all threads are complete it performs the cleanup code and then quits.

Alternatively you can use a WaitHandle such as as a ManualResetEvent per thread and wait for all of them to be signalled.

Mark Byers
There are many different places where threads leave the code. It's hard to make them back some where and join them
Xaqron
+2  A: 

A design where you lose track of your threads is not ideal.

Depending on how you spawn them it ought to be possible to track the status of each by associating some per-thread signalable object, then WaitAll on those signalable objects.

Each signalable object in turn should get signaled as its thread exits. When they are all signaled, you know the threads are all dead and you close down clean. You have to make sure that abnormal conditions in your threads do not result in that thread's associated signalable object remaining unset, or your WaitAll will never return. This means exceptions typically - could use try...finally to ensure the objects get signaled.

Your new pseudocode is

foreach (workitem in list of work)
  start up thread associated with a ManualResetEvent or similar

WaitAll for all events to be signalled
cleanup
Steve Townsend
+8  A: 

This is one place where using the new Task Parallel Library can make life much easier. Instead of creating threads, and spinning work up on the thread, you can use multiple tasks:

var task1 = Task.Factory.StartNew( () => DoTaskOneWork() );
var task2 = Task.Factory.StartNew( () => DoTaskTwoWork() );
var task3 = Task.Factory.StartNew( () => DoTaskThreeWork() );

// Block until all tasks are done

Task.WaitAll(new[] {task1, task2, task3} );
cleanUp(); // Do your cleanup

If the "tasks" are just downloading a bunch of individual files, you could even make this simpler using PLINQ:

var fileUrls = GetListOfUrlsToDownload();

fileUrls.AsParallel().ForAll( fileUrl => DownloadAndProcessFile(fileUrl) );

cleanUp(); // Do your cleanup
Reed Copsey
+1 assuming they are using .NET 4.0.
Mark Byers
+1 for simpler fire-and-forget solution
Steve Townsend
@Mark: I'm not assuming they are - but if they're not, I want to provide motivation to move ;)
Reed Copsey
Thanks Copsey, very useful
Xaqron