ManualResetEvent多线程进行,全部完成后,回调
static void Main(string[] args) { int count = 10; ManualResetEvent[] manuas = new ManualResetEvent[count]; for (int i = 0; i < count; i++) { manuas[i] = new ManualResetEvent(false); //封装对象,进行传值 ThreadPool.QueueUserWorkItem(new WaitCallback(testMethod), new aaa() { manualResetEvent=manuas[i], name="name"+i }); } if (WaitHandle.WaitAll(manuas)) { //All threads have completed. Console.WriteLine("true"); } else { Console.WriteLine("false"); } Console.ReadKey(); } public static void testMethod(object j) { //TODO: Add your code here //转化对象,do with data aaa a = j as aaa; if (a != null) { for (int i = 0; i < 1000; i++) { Console.WriteLine(a.name+"==>" + i); } ManualResetEvent e = a.manualResetEvent; e.Set(); } else { Console.WriteLine("传值失败"); } } class aaa { public ManualResetEvent manualResetEvent { get; set; } public string name { get; set; } }
以上有个bug:当线程数大于64个之后抛出异常
解决方法
封装一个MutipleThreadResetEvent类,
(1)封装MutipleThreadResetEvent类
using System; using System.Threading; namespace ConsoleApp5 { class MutipleThreadResetEvent : IDisposable { private readonly ManualResetEvent done; /// <summary> /// 需要等待执行的线程总数。 /// </summary> public readonly int total; /// <summary> /// 计数器:当前还有的多少个线程数 /// </summary> private long current; /// <summary> /// 构造函数 /// </summary> /// <param name="total">需要等待执行的线程总数</param> public MutipleThreadResetEvent(int total) { this.total = total; current = total; done = new ManualResetEvent(false); } public void SetDone() { //每一个子线程完成时-1 long lon = Interlocked.Decrement(ref current); if (lon == 0) {//到0时,向主线程发出信号,已经完成所有子线程操作,不用等了,进行下一步操作。 done.Set(); } } /// <summary> /// 等待所有线程执行完毕 /// </summary> public void WaitAll() { this.done.WaitOne(); } /// <summary> /// 释放对象占用的空间 /// </summary> public void Dispose() { ((IDisposable)done).Dispose(); } } }
(2)进行调用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp5 { class Program { static void Main(string[] args) { int num = 100; using (MutipleThreadResetEvent countdown = new MutipleThreadResetEvent(num)) { for (int i = 0; i < num; i++) { //开启num个线程(text),传递MutipleThreadResetEvent对象(countdown)给子线程(text) ThreadPool.QueueUserWorkItem(text, countdown); } //等待所有线程执行完毕 countdown.WaitAll(); } Console.WriteLine("已经完事了"); //进行下一步操作。 Console.ReadKey(); } public static void text(object obj) { //|自己的操作 Console.WriteLine("我"+(i++)); //接收参数 MutipleThreadResetEvent man = obj as MutipleThreadResetEvent; if (man == null) { Console.WriteLine("传值失败"); } else { //发送信号量 本线程执行完毕 man.SetDone(); } } } }
注意:在winform中会出现程序假死,那就再new Thread(delegate(){ dosth }){}.Start();吧!!