zoukankan      html  css  js  c++  java
  • C#多线程等待所有子线程结束

    在使用多线程过程中,可能会遇到在一些情况下必须等待子线程全部执行结束后主线程才进行下一步,

    做法如下:

     //在使用多线程过程中,可能会遇到在一些情况下必须等待子线程全部执行结束后主线程才进行下一步,做法如下
                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();
            }
        }
  • 相关阅读:
    普通图片转ascii码字符图
    基于RAF的一个小动画框
    HTML5给我们带来了什么
    记坑
    以后的博客可能会偏向游戏开发方向
    总结:js中4类修改样式的方法
    小记:css特殊性
    css小记
    探究绑定事件的this指向以及event传参的小问题
    手把手教你图片转ASCII码图
  • 原文地址:https://www.cnblogs.com/xwcs/p/13508542.html
Copyright © 2011-2022 走看看