I have a c# console application that creates up to 5 threads.
The threads are executing fine, but the UI thread shuts down as it finishes its work.
Is there a
If you are using .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));
The threads in the ThreadPool are background threads and that means an exiting application won't wait for them to complete.
You have a few options:
Parallel.ForEach(urls, url => MyMethod(url));
Ah - the ThreadPool is background. It is queued, but then your program ends. Finished. Program terminates.
Read up on Semaphores (WaitSignal) and wait- The threads in the callback at the end signal they are ended, when all have signaled that the main thread can continue.
Simplest hack to fix your problem.
In your program class:
static volatile int ThreadsComplete = 0;
In your "myMethod" at the end before return:
//ThreadsComplete++; //*edit* for safety's sake
Interlocked.Increment(ref ThreadsComplete);
In your main method before it returns/ends:
while(ThreadsComplete < urls.Count) { Thread.Sleep(10); }
The above essentially hacks together a WaitForAll synchronization method.
in Main:
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();
}
}
If you're using .net 4 then:
urls.AsParallel().ForAll(MyMethod);
Prior to .net 4 then start individual threads, keep them in a list and call Join(). The fact the workers are not background would keep them alive after the main thread exited, but the Join() is more explicit.
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();
}