• 关于线程间通信


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

      

  • 相关阅读:
    12306.cn网站自动登录器源代码
    从IL看C#
    CanvasRenderingContext2Dhtml5的关键
    慎用Response.Write()
    JPanel 的getGraphics
    怎么用swing绘图
    Win7 双硬盘启动出错处理
    paint repaint实现动画
    多线程一例
    画图,橡皮
  • 原文地址:https://www.cnblogs.com/kaixiangbb/p/3706669.html
Copyright © 2020-2023  润新知