zoukankan      html  css  js  c++  java
  • [.NET] Thread Separate Event

    撰写多线程对象时,执行速度是一项很重要的设计考虑。通常为了加快执行速度,会将执行运作逻辑的主线程,跟发出事件的事件线程做隔离设计。这样的隔离设计可以不让主线程,因为外部事件处理而停顿。而这样的设计下,为了简化线程管理,可以采用ThreadPool来完成事件线程的工作。简单的程序范例如下:

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var obj = new ClassA();
                obj.NotifyArrived += new Action<int>(obj_NotifyArrived);
                obj.Start();
                Console.ReadLine();
                obj.Stop();
            }
    
            static void obj_NotifyArrived(int data)
            {
                Console.WriteLine(data);
            }
        }
    
        public class ClassA
        {
            // Fields
            private bool _isRunning = true;
    
    
            // Methods    
            public void Start()
            {
                Thread thread = new Thread(this.Run);
                thread.Start();
            }
    
            public void Stop()
            {
                _isRunning = false;
            }
    
            private void Run()
            {
                int i = 0;
                while (_isRunning == true)
                {
                    Thread.Sleep(100);
                    this.OnNotifyArrived(i++);
                }
            }
    
    
            // Events
            public event System.Action<int> NotifyArrived;
            private void OnNotifyArrived(int data)
            {
                WaitCallback handlerDelegate = delegate(object state)
                {
                    var handler = this.NotifyArrived;
                    if (handler != null)
                    {
                        handler(data);
                    }
                };
                ThreadPool.QueueUserWorkItem(handlerDelegate);
            }
        }
    }
    

    但是这样的隔离设计,却无法满足「必须按照先来后到去处理事件」这样的行为要求。因为ThreadPool只是单纯的为每一个WaitCallback委派,分派一条线程去做处理,而每条线程之间并没有设定执行先后顺序的能力。

    这个问题困扰了我几天,后来想到一个解法。在主线程跟事件线程之间,垫一层Queue做隔离,将要执行的WaitCallback委派都存放进这个Queue。并且通过Lock的机制,强迫一次只能有一个线程去处理Queue里面的WaitCallback委派。透过这样的设计,就可以完成将执行运作逻辑的主线程,跟发出事件的事件线程做隔离设计的工作。范例程序代码如下:

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var obj = new ClassB();
                obj.NotifyArrived += new Action<int>(obj_NotifyArrived);
                obj.Start();
                Console.ReadLine();
                obj.Stop();
            }
    
            static void obj_NotifyArrived(int data)
            {
                Console.WriteLine(data);
            }
        }
    
        public class ClassB
        {
            // Fields
            private bool _isRunning = true;
    
            private readonly object _eventSyncRoot = new object();
    
            private readonly Queue<WaitCallback> _eventDelegateQueue = new Queue<WaitCallback>();
    
    
            // Methods    
            public void Start()
            {
                Thread thread = new Thread(this.Run);
                thread.Start();
            }
    
            public void Stop()
            {
                _isRunning = false;
            }
    
            private void Run()
            {
                int i = 0;
                while (_isRunning == true)
                {
                    Thread.Sleep(100);
                    this.OnNotifyArrived(i++);
                }
            }
    
    
            // Events
            public event System.Action<int> NotifyArrived;
            private void OnNotifyArrived(int data)
            {
                // Queue EventDelegate
                WaitCallback eventDelegate = delegate(object state)
                {
                    var handler = this.NotifyArrived;
                    if (handler != null)
                    {
                        handler(data);
                    }
                };
    
                lock (_eventDelegateQueue)
                {
                    _eventDelegateQueue.Enqueue(eventDelegate);
                }
    
                // Run EventDelegate
                WaitCallback handlerDelegate = delegate(object state)
                {
                    lock (_eventSyncRoot)
                    {
                        WaitCallback runEventDelegate = null;
                        lock (_eventDelegateQueue)
                        {
                            if (_eventDelegateQueue.Count > 0)
                            {
                                runEventDelegate = _eventDelegateQueue.Dequeue();
                            }
                        }
    
                        if (runEventDelegate != null)
                        {
                            runEventDelegate(null);
                        }
                    }
                };
                ThreadPool.QueueUserWorkItem(handlerDelegate);
            }
        }
    }
    

    最后说一下,要完成这样的隔离设计。不使用ThreadPool,而改用一个独立Thread去处理WaitCallback委派,也是可行的设计。只不过独立一个线程去处理,就需要额外增加管理这个独立线程的工作,这就看每个人的选择跟考虑了。

  • 相关阅读:
    隐性改变display类型
    垂直居中-父元素高度确定的多行文本(方法二)
    去掉WIN7 桌面图标的小箭头
    搭建高可用mongodb集群(三)—— 深入副本集内部机制
    搭建高可用mongodb集群(二)—— 副本集
    搭建高可用mongodb集群(一)——配置mongodb
    Linux:Tomcat报错: Error creating bean with name 'mapScheduler' defined in ServletContext resource 的解决方法
    LINUX ORACLE 启动与关闭
    Linux 安装 Oracle 11g R2
    ORACLE 数据库优化原则
  • 原文地址:https://www.cnblogs.com/clark159/p/2411438.html
Copyright © 2011-2022 走看看