Logo

C#多线程等待所有子线程结束

photo

2022年06月30日

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

做法如下:

 //在使用多线程过程中,可能会遇到在一些情况下必须等待子线程全部执行结束后主线程才进行下一步,做法如下
            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();
        }
    }

 

所有附件
该文章没有附件.
本文为原创文章,请注意保留出处!

单元格显示特定图片的功能还是比较简单的,只是网上的资料很多,太乱。现在就给大家写个很简单的方法供大家...C#WinForm中DataGridView单元格显示图片

热门文章

修复群晖Synology Drive client右键菜单缺失问题 本教程主要解决windows10右键菜单中没有SynologyDrive菜单的问题,整体思路是找到...修复群晖SynologyDriveclient右键菜单缺失问题 作者:Pastore Antonio
1812 浏览量
docker如何查看一个镜像内部的目录结构及其内部都有哪些文件 前言:有时候我们会在docker上下载一个镜像,或者是上传一个镜像到docker上,甚至有时候就是在...docker如何查看一个镜像内部的目录结构及其内部都有哪些文件 作者:Pastore Antonio
1791 浏览量
configure: error: Package requirements (oniguruma) were not met configure:error:Packagerequirements(oniguruma)...configure:error:Packagerequirements(oniguruma)werenotmet 作者:Pastore Antonio
1530 浏览量
Adobe Acrobat Pro 激活 这里记录了一些AdobeAcrobat的激活教程和组件。浏览量:1,683 作者:Pastore Antonio
1528 浏览量
追寻日出,找回自己 为什么我要去追寻日出?其实我是一个很懒的人,每次都起不来,直到有一次我在租房中睡到了大天亮,阳光照...追寻日出,找回自己 作者:Pastore Antonio
1506 浏览量