C # multi-threaded console application - Console terminates before threads are completed

I have a C # console application that creates up to 5 threads.

Threads run fine, but the UI thread shuts off as it completes.

Is there a way to keep the main user interface thread running while the side threads are working?

foreach (var url in urls)
{
    Console.WriteLine("starting thread: " + url); 
    ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(myMethod), url);
}

I start my threads according to the code above.

+5
source share
6 answers

Threads in ThreadPool are background threads, and this means that the application exiting from it will not wait for them to complete.

You have several options:

  • wait for example semaphore
  • Sleep(), , .
  • TPL, Parallel.ForEach(urls, url => MyMethod(url));
+8

.NET 4.0:

var tasks = new List<Task>();

foreach(var url in urls)
{
    tasks.Add(Task.Factory.StartNew(myMethod, url));
}

// do other stuff...

// On shutdown, give yourself X number of seconds to wait for them to complete...
Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(30));
+6

Ah - ThreadPool - . , . . .

(WaitSignal) wait - , , , .

+2

.net 4, :

urls.AsParallel().ForAll(MyMethod);

.net 4 , Join(). , , , Join() .

        List<Thread> workers = new List<Thread>();
        foreach(var url in urls)
        {
            Thread t = new Thread(MyMethod) {IsBackground = false};
            workers.Add(t);
            t.Start(url);
        }

        foreach (var worker in workers)
        {
            worker.Join();
        }
+1

The simplest hack to fix your problem.

In your class of program:

static volatile int ThreadsComplete = 0;

In your "myMethod" at the end before returning:

//ThreadsComplete++; //*edit* for safety sake
Interlocked.Increment(ref ThreadsComplete);

In your main method, before returning / ending it:

while(ThreadsComplete < urls.Count) { Thread.Sleep(10); }

The above has essentially cracked the WaitForAll synchronization method.

0
source

in the main menu:

var m = new ManualResetEvent(false);
// do something
foreach (var url in urls)
{
  Console.WriteLine("starting thread: " + url); 
  ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(myMethod), url);
}
m.WaitOne();


private static void myMethod(object obj)
{
  try{
   // do smt
  }
  finally {
    m.Set();
  }
}
-1
source

All Articles