C#等待多个线程完成

我有一个Windows窗体应用程序,我正在检查所有串口,以查看是否已连接特定设备。

这就是我如何分拆每个线程。 下面的代码已经从主要的gui线程中分离出来。

foreach (cpsComms.cpsSerial ser in availPorts) { Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev)); t.Start((object)ser);//start thread and pass it the port } 

我希望下一行代码等到所有线程都完成。 我已经尝试在那里使用t.join ,但这只是线性处理它们。

 List threads = new List(); foreach (cpsComms.cpsSerial ser in availPorts) { Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev)); t.Start((object)ser);//start thread and pass it the port threads.Add(t); } foreach(var thread in threads) { thread.Join(); } 

编辑

我正在回顾这一点,我更喜欢以下内容

 availPorts.Select(ser => { Thread thread = new Thread(lookForValidDev); thread.Start(ser); return thread; }).ToList().ForEach(t => t.Join()); 

使用AutoResetEvent和ManualResetEvent类:

 private ManualResetEvent manual = new ManualResetEvent(false); void Main(string[] args) { AutoResetEvent[] autos = new AutoResetEvent[availPorts.Count]; manual.Set(); for (int i = 0; i < availPorts.Count - 1; i++) { AutoResetEvent Auto = new AutoResetEvent(false); autos[i] = Auto; Thread t = new Thread(() => lookForValidDev(Auto, (object)availPorts[i])); t.Start();//start thread and pass it the port } WaitHandle.WaitAll(autos); manual.Reset(); } void lookForValidDev(AutoResetEvent auto, object obj) { try { manual.WaitOne(); // do something with obj } catch (Exception) { } finally { auto.Set(); } } 

最简单和最安全的方法是使用CountdownEvent。 见阿尔巴哈里 。

您可以使用CountDownLatch:

 public class CountDownLatch { private int m_remain; private EventWaitHandle m_event; public CountDownLatch(int count) { Reset(count); } public void Reset(int count) { if (count < 0) throw new ArgumentOutOfRangeException(); m_remain = count; m_event = new ManualResetEvent(false); if (m_remain == 0) { m_event.Set(); } } public void Signal() { // The last thread to signal also sets the event. if (Interlocked.Decrement(ref m_remain) == 0) m_event.Set(); } public void Wait() { m_event.WaitOne(); } } 

示例如何使用它:

 void StartThreads { CountDownLatch latch = new CountDownLatch(availPorts.Count); foreach (cpsComms.cpsSerial ser in availPorts) { Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev)); //start thread and pass it the port and the latch t.Start((object)new Pair(ser, latch)); } DoSomeWork(); // wait for all the threads to signal latch.Wait(); DoSomeMoreWork(); } // In each thread void NameOfRunMethod { while(running) { // do work } // Signal that the thread is done running latch.Signal(); } 

在生成线程后,将线程结果存储在列表中并迭代列表 – 然后在迭代调用连接期间。 你仍然线性加入,但它应该做你想要的。