6

Possible Duplicate:
C#: Waiting for all threads to complete

I have a console app that spawns some threads and then exits. Each thread takes roughly ~20 seconds to complete. It appears as though the console app is spawning the threads and then exiting before the threads have a chance to complete.

How do I tell the console app not to exit until all threads it has spawned have completed?

Community
  • 1
  • 1
downatone
  • 1,936
  • 2
  • 23
  • 30
  • Great set of answers people. @JohnEgbert - threads were being spawned in a loop, so your solution was just what I was looking for. Although I'm sure others will gain from the provided solutions. – downatone May 05 '11 at 20:35

7 Answers7

8

You can to use a CountDownEvent.

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static CountdownEvent countdown;

        static void Main(string[] args)
        {
            countdown = new CountdownEvent(1);
            for (int i = 1; i < 5; i++)
            {
                countdown.AddCount(); //add a count for each (BEFORE starting thread .. Thanks, Brian!)
                //do stuff to start background thread
            }
            countdown.Signal(); //subtract your initial count
            countdown.Wait(); //wait until countdown reaches zero
            //done!
        }

        static void backgroundwork()
        {
            //work
            countdown.Signal(); //signal this thread's completion (subtract one from count)
        }
    }
}
Tim Coker
  • 6,484
  • 2
  • 31
  • 62
  • 2
    I use this pattern a lot. It works quite well. Note, that the `AddCount` should really happen before starting the threads, otherwise there is an extremely subtle bug that could cause the event to get signalled prematurely if the first thread completes before `AddCount` was called. – Brian Gideon May 05 '11 at 18:55
  • Never thought of that, but it could happen. Would be rare, but extremely annoying to troubleshoot. – Tim Coker May 05 '11 at 19:00
  • Ha..yeah, rare is understatement especially if the thread is doing any kind of useful work. But, man, that would be one hell of bug to troubleshoot for sure! – Brian Gideon May 05 '11 at 19:07
6

Are the threads spawned for a loop? If so a Parallel.ForEach would work:

ParallelOptions options = new ParallelOptions();
                    Parallel.ForEach(items, options, item=>
                    {
// Do Work here
                    });
Community
  • 1
  • 1
John Egbert
  • 5,496
  • 8
  • 32
  • 44
  • If you're not actually going to set any options, I'd probably go for the overload that doesn't require you to pass in a `ParallelOptions` and just leave out that first line entirely. – Joel Mueller May 05 '11 at 21:23
3

As long as the Thread is not a background-thread (.IsBackground), the app should stay alive:

static void Main()
{
    Thread thread = new Thread(MoreStuff);
    thread.IsBackground = false;
    thread.Start();
    Console.WriteLine("Main thread exiting");
}
static void MoreStuff()
{
    Console.WriteLine("Second thread starting");
    Thread.Sleep(5000); // simulate work
    Console.WriteLine("Second thread exiting");
}

Nothing else is needed. Note that the ThreadPool will use background threads; is the problem perhaps that you are using ThreadPool here?

Note: if the second thread hasn't actually started there might be a small race where it can exit prematurely; you might want to gate the threads starting.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

You can use Thread.Join to wait for a thread to complete.

C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
2

How are you launching the threads? It really depends, but if you are just using the Thread class, then call yourThread[i].Join() from the main thread to ensure that all threads complete.

Look into the Tasks and Task Factory to handle things a lot more cleanly than in years past.

pickypg
  • 22,034
  • 5
  • 72
  • 84
2

Call Thread.Join() on all of the Threads that you start after they have started. This will block the current thread until the thread is complete.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
0

You should probably use synchronization and wait for any spawned threads to complete their work, either by blocking the main thread with calls to Thread.Join or using signalling (e.g. using a Monitor or one of the other options for this).

Alternatively you can simply make the spawned threads run as foreground threads, by setting the IsForeground property (afaicr). This will keep the application alive until the threads have terminated, but you will still see the console window disappear as the main thread exits.

Morten Mertner
  • 9,414
  • 4
  • 39
  • 56