1. 程式人生 > 實用技巧 >C#多執行緒等待所有子執行緒結束

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();
        }
    }