在使用多线程过程中,可能会遇到在一些情况下必须等待子线程全部执行结束后主线程才进行下一步,
做法如下:
//在使用多线程过程中,可能会遇到在一些情况下必须等待子线程全部执行结束后主线程才进行下一步,做法如下 List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();//创建线程等待集合 for (int i = 0; i < 64; i++) //WaitHandles 的数目必须少于或等于 64 个,所以最大线程数为64 { MB m = new MB();//自定义类,用于传参 m.mre= new ManualResetEvent(false); m.ID = i; manualEvents.Add(m.mre); ThreadPool.QueueUserWorkItem(ThreadMethod, m); } WaitHandle.WaitAll(manualEvents.ToArray());//等待所有线程结束 Console.WriteLine("Thread Finished!");
private static void ThreadMethod(object obj) { MB m = (MB)obj; Thread.Sleep(1000);//等待1秒,用于模拟系统在处理事情 m.mre.Set();//将事件设置为终止状态 Console.WriteLine("Thread execute:" + m.ID); }
以上方法在处理时当线程数超过64时报错 WaitHandles 的数目必须少于或等于 64 个,所以最大线程数为64
解决方法如下:
using (var countdown = new MutipleThreadResetEvent(list.Count)) { for (int i = 0; i < list.Count; i++) { //开启N个线程,传递MutipleThreadResetEvent对象给子线程 Param p = new Param(); p.countdown = countdown; p.Path = pa[i]; ThreadPool.QueueUserWorkItem(MyHttpRequest, p); } //等待所有线程执行完毕 countdown.WaitAll(); }
public class MutipleThreadResetEvent: IDisposable { private readonly ManualResetEvent done; private readonly int total; private long current; /// <summary> /// 构造函数 /// </summary> /// <param name="total">需要等待执行的线程总数</param> public MutipleThreadResetEvent(int total) { this.total = total; current = total; done = new ManualResetEvent(false); } /// <summary> /// 唤醒一个等待的线程 /// </summary> public void SetOne() { // Interlocked 原子操作类 ,此处将计数器减1 if (Interlocked.Decrement(ref current) == 0) { //当所以等待线程执行完毕时,唤醒等待的线程 done.Set(); } } /// <summary> /// 等待所以线程执行完毕 /// </summary> public void WaitAll() { done.WaitOne(); } /// <summary> /// 释放对象占用的空间 /// </summary> public void Dispose() { ((IDisposable)done).Dispose(); } }