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...");
}
}
}
CLR 显示实现事件 EventSet内部管理一个字典的更多相关文章
- [转]3天搞定的小型B/S内部管理类软件定制开发项目【软件开发实战10步骤详解】
本文转自:http://www.cnblogs.com/jirigala/archive/2010/10/07/1845275.html 2010-10-07 21:39 by 通用C#系统架构, 5 ...
- 关于vue事件监听的一个问题
由于新工作需要用vue,所以最近接触最多的也是vue,因为之前一直在用react,所以对于vue上手还是很快的.我也尽量找一些他们两个的异同点,除了多了一些辅助用的方法以外,最大的不同应该是对于组件间 ...
- [CLR via C#]21. 自动内存管理(垃圾回收机制)
目录 理解垃圾回收平台的基本工作原理 垃圾回收算法 垃圾回收与调试 使用终结操作来释放本地资源 对托管资源使用终结操作 是什么导致Finalize方法被调用 终结操作揭秘 Dispose模式:强制对象 ...
- Android软键盘的隐藏显示、事件监听的代码
把开发过程中重要的一些内容片段做个珍藏,如下资料是关于Android软键盘的隐藏显示.事件监听的内容,应该是对小伙伴们有所用途. public class ResizeLayout extends L ...
- CLR VIA C#事件
事件是类型的一个成员,用来在事情发生的时候通知注册了该事件的成员. 事件和观察者模式十分的相似,所以事件应该提供如下几种能力 1.能让对象的方法登记对他的关注 2.能让对象的方法取消对他的关注 3.能 ...
- js闭包(函数内部嵌套一个匿名函数:这个匿名函数可将所在函数的局部变量常驻内存)
js闭包(函数内部嵌套一个匿名函数:这个匿名函数可将所在函数的局部变量常驻内存) 一.总结 1.闭包:就是在一个函数内部嵌套一个匿名函数,这个匿名函数可以访问这个函数的变量. 二.要点 闭包 闭包的相 ...
- 一个字典通过dictionaryWithDictionary 他们的内存指针是不同的
一个字典通过dictionaryWithDictionary 他们的内存指针是不同的 来自为知笔记(Wiz)
- 有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'}
题目:有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'} 第一种方法: d = {'a': 1, 'b': 2}d = {value: k ...
- Python把两个列表合成一个字典
简单粗暴上代码 A= [] B = [] C= dict(map(lambda x,y:[x,y],A,B)) 酱紫,就合成了一个字典
随机推荐
- 对Tornado异步操作Sqlalchemy方法的选定 不错
使用原因 在一个实时通讯的项目中,由于需要使用Websocket这一协议,便在Python框架中选定了Tornado,也同时使用了Sqlalchemy这一ORM框架. 大家都知道Tornado有异步非 ...
- VUE API 重点
VUE API 重点 生命周期方法 每个组件都有生命周期,是向 ReactJs 学习的. computed 在一个组件声明一个人,人有名,人有姓,输入姓和名.((&--&%--& ...
- mysql + unidac 使用事务例子
//备注:mysql必须是使用innoDB引擎才支持事务功能,否则以下事务相关代码将失效.//SQL SERVER和Oracle还没试,明天回公司试了再发代码.procedure TForm1.btn ...
- Python模块详解以及import本质,获得文件当前路径os.path.abspath,获得文件的父目录os.path.dirname,放到系统变量的第一位sys.path.insert(0,x)
模块介绍 1.定义: 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test) 包:用来从逻 ...
- bootstrap+css进行页面布局
效果 用到了bootstrap中的表格css.圆形css.以及上一页下一页css. 布局页面,填充数据,实现js动态效果(比如点击下一页,上一页),逐步完善. 不仅仅要会使用bootstrap中的样式 ...
- js中如何将字符串转化为时间,并计算时间差
在前台页面开发时通常会用到计算两个时间的时间差,先在此附上实现方法 //结束时间 end_str = ("2014-01-01 10:15:00").replace(/-/g,&q ...
- resharper activate
K03CHKJCFT-eyJsaWNlbnNlSWQiOiJLMDNDSEtKQ0ZUIiwibGljZW5zZWVOYW1lIjoibnNzIDEwMDEiLCJhc3NpZ25lZU5hbWUiO ...
- oracle导入数据和编码问题
配置contrl文件 load data characterset utf8 append into table role_res_gold fields terminated by ';' TRAI ...
- springboot成神之——拦截器
本文介绍spring boot拦截器 创建拦截器类LogInterceptor.java 创建拦截器类OldLoginInterceptor.java 拦截器配置类WebMvcConfig.java ...
- in not in 和 null , in 判断范围中可以包含null,而not in判断不能包括null
oracle中,任何字符串与null比较得到的结果都是null,而 oracle的判断条件为null时就退出判断(?) 因此判断某个字符串是否在一个集合中时,not in 和 in的结果完全不一样,如 ...