netframework中等待多个子线程执行完毕并计算执行时间
2019-05-26 23:28
561 查看
本文主要描述在.netframework中(实验环境.netframework版本为4.6.1)提供两种方式等待多个子线程执行完毕。
- ManualResetEvent
在多线程中,将ManualResetEvent实例作为方法传入,线程执行完毕后可以设置标志位来标识当前线程已经执行完毕。代码如下:
List<ManualResetEvent> manualResetEvents = new List<ManualResetEvent>(); /// <summary> /// ManualResetEvent标志多线程是否执行完毕 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_ManualResetEvent_Click(object sender, EventArgs e) { // SetBtnEnabled(false); Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < threadCount; i++) { ManualResetEvent manualReset = new ManualResetEvent(false); manualResetEvents.Add(manualReset); ThreadPool.QueueUserWorkItem(ManualResetEventMethod, manualReset); } //等待所有线程执行完毕 WaitHandle.WaitAll(manualResetEvents.ToArray()); //暂停watch,获取多线程执行时间 watch.Stop(); long time = watch.ElapsedMilliseconds; lab_time.Text = time.ToString(); // SetBtnEnabled(true); //释放句柄 manualResetEvents.Clear(); } private void ManualResetEventMethod(object obj) { Thread.Sleep(1000); ManualResetEvent mre = (ManualResetEvent)obj; mre.Set(); }View Code
注意:
在WaitHandle.WaitAll方法中,等待的句柄不能超过64,所以每次用完后,需要手动调用Clear方法进行释放。
如果等待的线程超过64个,可以参考博客:https://www.cnblogs.com/xiaofengfeng/archive/2012/12/27/2836183.html,在该博客中,通过对ManualResetEvent的封装,能够使等待的句柄超过64(测试环境下一次起1000个线程,没有问题)
- Monitor
在主线程中通过Monitor.Wait(locker)达到阻塞的目的,子线程执行完毕通过 Monitor.Pulse(locker)通知主线程,直到所有子线程执行完成,主线程再继续执行,代码如下:
object locker = new object(); int threadCount = 1000; int finshCount = 0; /// <summary> /// Monitor线程之间同步标记多线程执行完毕 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Monitor_Click(object sender, EventArgs e) { finshCount = 0; SetBtnEnabled(false); Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < threadCount; i++) { Thread trd = new Thread(new ParameterizedThreadStart(MonitorMethod)); trd.Start(i); } lock (locker) { while (finshCount != threadCount) { Monitor.Wait(locker);//等待 } } //所有线程执行完毕,获取执行时间 watch.Stop(); long time = watch.ElapsedMilliseconds; lab_time.Text = time.ToString(); SetBtnEnabled(true); } private void MonitorMethod(object obj) { Thread.Sleep(1000); lock (locker) { finshCount++; Monitor.Pulse(locker); //完成,通知等待队列,告知已完,执行下一个。 } }View Code
在一次开启10、1000个线程两种环境下,分别测试以上两种方式,ManualResetEvent在多次执行时,前几次耗时会比较大,后续耗时会减少并且稳定下来,接近 Monitor的速度。相对而言,Monitor的效率更高。
如果了解过go语言,会发现通过sync包下的WaitGroup也可以达到同样的目的,代码如下:
package main import ( "fmt" "sync" "time" ) var wg sync.WaitGroup var count = 1000 func main() { startTime := time.Now().Unix() wg.Add(count) for i := 0; i < count; i++ { go func() { defer wg.Done() time.Sleep(time.Second) }() } fmt.Println("waiting for all goroutine") wg.Wait() endTime := time.Now().Unix() fmt.Printf("all goroutine is done! time:%v s", (endTime-startTime)) }
相较而言,go语言的协程效率最高
相关文章推荐
- 进阶篇:等待多个子线程完毕再执行主线程的方法之CountDownLatch(十二)
- c#等待所有子线程执行完毕方法
- Java主线程等待所有子线程执行完毕再执行解决办法集
- Java多线程--让主线程等待所有子线程执行完毕
- 线程池等待一定数目的线程执行完毕之后返回结果
- 今天遇到一个问题:在程序中加入的定时触发器,当时出现这样一个问题,触发器定时2秒,程序从后台查询数据经过复杂处理后时间超过了2秒,我查阅好些网络上说有可能触发器等待程序执行完毕后,在触发下一次,也有说
- java主线程等待所有子线程执行完毕在执行(常见面试题)
- java主线程等待所有子线程执行完毕在执行(常见面试题)
- 异常信息:CLR无法从COM 上下文0x645e18 转换为COM上下文0x645f88,这种状态已持续60秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作.这种情况通常会影响到
- c#等待所有子线程执行完毕方法
- 理解CountDownLatch和CyclicBarrier(主线程等待所有子线程执行完毕在执行)
- 主线程里创建N个子线程,等待N个子线程全部执行完
- Java多线程--主线程等待所有子线程执行完毕
- Java多线程--让主线程等待所有子线程执行完毕
- Java等待多个线程执行完毕
- java 等待线程/线程池执行完毕
- java实现多个子线程执行完毕后,再执行主线程
- CLR 无法从 COM 上下文 0x1a2740 转换为 COM 上下文 0x1a28b0,这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作
- Java多线程--让主线程等待所有子线程执行完毕
- 主线程等待子线程执行完毕后再执行