To wait for multiple threads to finish, you can use several EventWaitHandle and then call WaitHandle.WaitAll to block the main thread while all events are signaled:
// we need to keep a list of synchronization events var finishEvents = new List<EventWaitHandle>(); for (int i = 0; i < records.Count; i++ ) { // for each job, create an event and add it to the list var signal = new EventWaitHandle(false, EventResetMode.ManualReset); finishEvents.Add(signal); // we need to catch the id in a separate variable // for the closure to work as expected var id = records[i]; var thread = new Thread(() => { // do the job ThreadJob(id); // signal the main thread signal.Set(); }); } WaitHandle.WaitAll(finishEvents.ToArray());
Since most of these threads will be suspended in most cases, it would be better to use ThreadPool in this case, so you can replace the new Thread with:
ThreadPool.QueueUserWorkItem(s => { ThreadJob(id); signal.Set(); });
When you are finished with events, do not forget to delete them:
foreach (var evt in finishEvents) { evt.Dispose(); }
[change]
To put it all in one place, here is what your sample code looks like:
static Semaphore _sem = new Semaphore(3, 3); // Capacity of 3 static List<string> _records = new List<string>(new string[] { "aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh" }); static void Main() { var finishEvents = new List<EventWaitHandle>(); for (int i = 0; i < _records.Count; i++) { var signal = new EventWaitHandle(false, EventResetMode.ManualReset); finishEvents.Add(signal); var id = _records[i]; var t = new Thread(() => { ThreadJob(id); signal.Set(); }); t.Start(); } WaitHandle.WaitAll(finishEvents.ToArray()); Console.WriteLine(_records.Count); Console.ReadLine(); } static void ThreadJob(object id) { Console.WriteLine(id + " wants to enter"); _sem.WaitOne(); Console.WriteLine(id + " is in!"); Thread.Sleep(1000); Console.WriteLine(id + " is leaving"); lock (_records) { _records.Remove((string)id); } _sem.Release(); }
(note that I used Semaphore instead of SemaphoreSlim because I don't have .NET 4 on this computer and I wanted to test the code before updating the response)
Groo source share