在开发中遇到过这样的需求,主线程中开启多个子线程来处理数据以提高效率,待所有的子线程执行完成任务后,主线程继续完成后续的操作。一番思考后,思路出来了,我的做法是定义一个全局整型的静态变量,每个子线程完成任务后变量加1。主线程里有一个while死循环,每次循环判断这个变量的值,如果值为开启的线程数则表示所有子线程已经完成了任务,然后跳出循环继续执行后续的操作。逻辑上来看这是没有任何问题的,于是很快就完成了编码运行测试。结果自然和预料中的一样没啥问题。
运行过程中发现cpu使用率很高,如果执行的时间过长总能感觉到风扇转的很厉害,很担心会吧自己的本本烧坏。于是想到了优化代码,可是如何下手从哪里下手呢,思考良久想到了一个很二的办法,在循环里加了句Thread.Slee()。这样,每次循环后让主线程睡眠一段时间的方法来降低循环cpu的高使用率。这样优化代码,运行了一段时间。但也没和之前进行过比较,效率是高了还是低了无所知晓,心里总在嘀咕这样的代码看着很是别扭。尽管没有几行的代码,反正看着就是不舒服、不顺眼,于是又有了优化的念头。这次的优化不再是自己苦思冥想,应该百度一下,看人家是如何实现的。
一番搜索后,终于找到了关键字“ManualResetEvent”,然后就是MSDN查阅相关文档,以下为练习的代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ManualResetEventTest { class Program { static void Main(string[] args) { ManualResetEventContext[] contexts = new ManualResetEventContext[5]; ManualResetEvent[] manualResetEvents = new ManualResetEvent[5]; for (int i = 0; i < 5; i++) { ManualResetEvent e = new ManualResetEvent(false); manualResetEvents[i] = e; contexts[i] = new ManualResetEventContext(e, doSomeThing) { ID = i }; ThreadPool.QueueUserWorkItem(contexts[i].Invoke, contexts[i]); } WaitHandle.WaitAll(manualResetEvents); Console.WriteLine("所有子线程执行完成"); Console.Read(); } static void doSomeThing(object state) { ManualResetEventContext context = state as ManualResetEventContext; //do... Thread.Sleep(1000*60); Console.WriteLine(string.Format("第{0}个子线程执行完成", context.ID)); } } public class ManualResetEventContext { public int ID { get; set; } public ManualResetEvent ManualResetEvent { get; set; } private WaitCallback _callback; public ManualResetEventContext(ManualResetEvent manualResetEvent, WaitCallback callback) { this.ManualResetEvent = manualResetEvent; this._callback = callback; } public void Invoke(object state) { try { _callback(state); } finally { //子线程操作完成后必须调用此方法 ManualResetEvent.Set(); } } } }
运行结果: