I have a List with items that I want to download. I use a for Loop to iterate the list.
For each item in this List I start a new Thread that references the item. My
I solved this very problem in .Net 3.5 by creating threads and loading them into a queue. Then I read a thread from the queue, start it, and increment the running thread count. I keep doing this until I hit the upper limit.
As each thread finishes it invokes a callback method that decrements the running count and signals the queue reader to start more threads. For additional control you can use a dictionary to keep track of running threads, keyed by ManagedThreadId, so you can signal threads to stop early or report progress.
Sample console app:
using System;
using System.Collections.Generic;
using System.Threading;
namespace ThreadTest
{
class Program
{
static void Main(string[] args)
{
Supervisor supervisor = new Supervisor();
supervisor.LaunchThreads();
Console.ReadLine();
supervisor.KillActiveThreads();
Console.ReadLine();
}
public delegate void WorkerCallbackDelegate(int threadIdArg);
public static object locker = new object();
class Supervisor
{
Queue pendingThreads = new Queue();
Dictionary activeWorkers = new Dictionary();
public void LaunchThreads()
{
for (int i = 0; i < 20; i++)
{
Worker worker = new Worker();
worker.DoneCallBack = new WorkerCallbackDelegate(WorkerCallback);
Thread thread = new Thread(worker.DoWork);
thread.IsBackground = true;
thread.Start();
lock (locker)
{
activeWorkers.Add(thread.ManagedThreadId, worker);
}
}
}
public void KillActiveThreads()
{
lock (locker)
{
foreach (Worker worker in activeWorkers.Values)
{
worker.StopWork();
}
}
}
public void WorkerCallback(int threadIdArg)
{
lock (locker)
{
activeWorkers.Remove(threadIdArg);
if (activeWorkers.Count == 0)
{
Console.WriteLine("no more active threads");
}
}
}
}
class Worker
{
public WorkerCallbackDelegate DoneCallBack { get; set; }
volatile bool quitEarly;
public void DoWork()
{
quitEarly = false;
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " started");
DateTime startTime = DateTime.Now;
while (!quitEarly && ((DateTime.Now - startTime).TotalSeconds < new Random().Next(1, 10)))
{
Thread.Sleep(1000);
}
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " stopped");
DoneCallBack(Thread.CurrentThread.ManagedThreadId);
}
public void StopWork()
{
quitEarly = true;
}
}
}
}