zoukankan      html  css  js  c++  java
  • CLR 显示实现事件 EventSet内部管理一个字典

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication5
    {
        public sealed class EventKey { }
        public sealed class EventSet
        {
            //内部管理一个事件的字典,key为每次生成的所以哈希码是不同的,以确认字典的键不会重复
            private readonly Dictionary<EventKey, Delegate> m_events = new Dictionary<EventKey, Delegate>();
            /// <summary>
            /// Monitor.Enter线程安全,在指定对象上获取排它锁
            /// </summary>
            /// <param name="eventKey"></param>
            /// <param name="handle"></param>
            public void Add(EventKey eventKey,Delegate handle)
            {
                //获取指定对象上的排它锁,线程安全,确保我在增加一个键值对的时候不会发生导致线程不安全的情况
                Monitor.Enter(m_events);
                Delegate d;
                //获取指定键相关联的值,关键是这样可以防止字典的键不存在时,还要写代码去判断键是否存在的情况
                m_events.TryGetValue(eventKey, out d);
                //将两个委托的调用列表链接在一起
                m_events[eventKey] = Delegate.Combine(d, handle);
                //释放指定对象上的排它锁
                Monitor.Exit(m_events);
              
            }
            public void Remove(EventKey eventKey, Delegate handler)
            {
                Monitor.Enter(m_events);
                Delegate d;
                if (m_events.TryGetValue(eventKey, out d))
                {
                    //从指定的源上删除某个委托,内部执行多路广播委托,删除后委托链的头部地址会改变
                    d = Delegate.Remove(d, handler);
    
                    //删除后还有委托,设置新的头部地址
                    if (d != null)
                    {
                        m_events[eventKey] = d;
                    }
                    else
                    {
                        m_events.Remove(eventKey);
                    }
                    Monitor.Exit(m_events);
    
                }
            }
            //激发事件委托
            public void Raise(EventKey eventKey, Object sender, EventArgs e)
            {
                Delegate d;
                Monitor.Enter(m_events);
                m_events.TryGetValue(eventKey,out d);
                Monitor.Exit(m_events);
                if (d != null)
                {
                    d.DynamicInvoke(new object[] {sender,e });
                }
            }
            
            
    
        }
        public class FooEventArgs : EventArgs { }
        public class TypeWithLotsOfEvents
        {
    
            private readonly EventSet m_eventSet = new EventSet();
            protected EventSet EventSet { get { return m_eventSet; } }
            //对于TypeWithLotsOfEvents的每个实例对应的 下列字段key是唯一的
            protected static readonly EventKey s_fooEventKey = new EventKey();
            
            public event EventHandler<FooEventArgs> FOO
            {
                add { m_eventSet.Add(s_fooEventKey, value); }
                remove { m_eventSet.Remove(s_fooEventKey, value); }
            }
    
            protected virtual void OnFOO(FooEventArgs e)
            {
                m_eventSet.Raise(s_fooEventKey, this, e);
            }
            public void SimulateFOO()
            {
                OnFOO(new FooEventArgs());
            }
               
    
        }
        class Program
        {
            static void Main(string[] args)
            {
                TypeWithLotsOfEvents twle = new TypeWithLotsOfEvents();
                twle.FOO += Twle_FOO;
                twle.SimulateFOO();
                Console.ReadKey();
                
            }
    
            private static void Twle_FOO(object sender, FooEventArgs e)
            {
                Console.WriteLine("Hading Foo Event here...");
            }
        }
    }
  • 相关阅读:
    MHA自动切换流程
    手写源码之 简单实现on emit off
    手写源码 -- bind,call,aplly
    多维数组转化为一维数组
    electron+vue中使用nodeJs的fs模块以及上传文件
    制作海报
    vue中引入播放器(百度播放器和腾讯云播放器)
    webpack配置
    webpack
    css样式
  • 原文地址:https://www.cnblogs.com/kexb/p/5148219.html
Copyright © 2011-2022 走看看