在使用多線程過程中,可能會遇到在一些情況下必須等待子線程全部執行結束后主線程才進行下一步,
做法如下:
//在使用多線程過程中,可能會遇到在一些情況下必須等待子線程全部執行結束后主線程才進行下一步,做法如下 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(); } }