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)) 酱紫,就合成了一个字典
随机推荐
- [BZOJ5297][CQOI2018]社交网络
bzoj luogu sol 就是求以\(1\)为根的生成树的数量. 直接矩阵树定理. code #include<cstdio> #include<algorithm> #i ...
- SP104 HIGH - Highways
vjudge luogu 题意 就是要你求无向图的生成树个数.\(n\le 12\),保证答案不爆\(long long\). sol 矩阵树定理直接上. 如果怕掉精可以写整数意义下的高斯消元,需要辗 ...
- MAC OS X常用命令总结
附录:UNIX常用命令 ============================================================================ 1. cd ...
- 12C 对表分区维护的增强
Oracle Database 12c对表分区变化比较多,共分为下面几点 1.在线移动分区:通过MOVE ONLINE关键字实现在线分区移动.移动过程中,对表和被移动的分区可以执行查询操作, DML语 ...
- 老齐python-基础1
1.基本对象类型 1.1数: >>> 3 #基本数字 3 >>> 3333 3333 >>> 3.222 3.222 >>&g ...
- 【转】JMeter中对于Json数据的处理方法
Json 作为一种数据交换格式在网络开发,特别是 Ajax 与 Restful 架构中应用的越来越广泛.而 Apache 的 JMeter 也是较受欢迎的压力测试工具之一,但是它本身没有提供对于 Js ...
- Python 列表笔记
列表解析 squares = []for i in range(1,11): square = i**2 squares.append(square)print squares ########## ...
- java数组遍历 删除remove
package com.b; import java.util.ArrayList; //数组遍历删除,添加 public class Core2 { private String name; pri ...
- Vue.js:template
ylbtech-Vue.js: 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 9.返回顶部 1 ...
- Maven使用阿里云镜像
Maven确实是个好用的东西,不过在国内的话下载速度不够快,推荐使用阿里云的镜像,配置方法还是比较简单,这里是全局的配置文件 settings.xml中的内容: <settings xmlns= ...