关于线程间通信

  在开发中遇到过这样的需求,主线程中开启多个子线程来处理数据以提高效率,待所有的子线程执行完成任务后,主线程继续完成后续的操作。一番思考后,思路出来了,我的做法是定义一个全局整型的静态变量,每个子线程完成任务后变量加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();
            }
        }
    }
}
运行结果:

  

原文地址:https://www.cnblogs.com/kaixiangbb/p/3706669.html