11.Events
1.A type that defines an event member allows the type (or instances of the type) to notify other objects that something special has happened
2.defining an event member means that a type is offering the following capabilities:
1.A method can register its interest in the event
2.A method can unregister its interest in the event.
3.Registered methods will be notified when the event occurs.
because they maintain a list of the registered methods. When the event occurs, the type notifies all of the registered methods in the collection
3.The common language runtime’s (CLR’s) event model is based on delegates.
A delegate is a typesafe way to invoke a callback method.
Callback methods are the means by which objects receive the notifications they subscribed to.
示例:

the application initializes by constructing an instance of MailManager.
MailManager offers a NewMail event. When the Fax and Pager
objects are constructed, they register an instance method with MailManager’s NewMail event so that
MailManager knows to notify the Fax and Pager objects when new email messages arrive.
Now,when MailManager receives a new email message (sometime in the future), it will raise the NewMail event, giving all of the registered methods an opportunity to process the new message in any way they want.
1.Designing a Type That Exposes an Event
steps:
1.Define a type that will hold any additional information that should be sent to receivers of the event notification
This additional information needs to be encapsulated into its own class, which typically contains a bunch of private fields along with some read-only public properties to expose these fields.
By convention, classes that hold event information to be passed to the event handler should be derived from System.EventArgs, and the name of the class should be suffixed with EventArgs.

2.Define the event member
using the C# keyword event.
Each event member is given accessibility(which is almost always public so that other code can access the event member),a type of delegate indicating the prototype of the method(s) that will be called
a name (which can be any valid identifier)

NewMail is the name of this event. The type of the event member is EventHandler<NewMailEventArgs>, which means that all receivers of the event notification must supply a callback method whose prototype matches that of the EventHandler<NewMailEventArgs> delegate type.
Because the generic System.EventHandler delegate is defined as follows.
public delegate void EventHandler<TEventArgs>(Object sender, TEventArgs e);
the method prototypes must look like the following.
void MethodName(Object sender, NewMailEventArgs e);
3.Define a method responsible for raising the event to notify registered objects that the event has occurred
By convention, the class should define a protected
virtual method that is called by code internally within the class and its derived classes when the event is to be raised.
This method takes one parameter,a NewMailEventArgs object, which includes the information passed to the objects receiving the notification.

优化:define an extension method that encapsulates this thread-safety logic


A class that uses MailManager as a base type is free to override the OnNewMail method.
This capability gives the derived class control over the raising of the event. The derived class can handle
the new email message in any way it sees fit.
Usually, a derived type calls the base type’s OnNewMail method so that the registered method(s) receive the notification. However, the derived class might decide to disallow the event from being forwarded.
4.Define a method that translates the input into the desired event

其他知识点:
1.The EventArgs class is defined in the Microsoft .NET Framework Class Library (FCL)

this type is nothing to write home about. It simply serves as a base type from which other types can derive.
Many events don’t have any additional information to pass on.just use EventArgs.Empty rather than constructing a new EventArgs object.
2.why the event pattern requires the sender parameter to always be of type Object?
(1) the cast is required, so the sender parameter might as well be typed as Object.like
void MethodName(MailManager sender, NewMailEventArgs e);
(2)typing the sender parameter as Object is just flexibility.
It allows the delegate to be used by multiple types that offer an event that passes a NewMailEventArgs object.
this is to add additional consistency to the pattern, making it easier for developers to learn and implement the pattern
For example, a PopMailManager class could use the delegate even if this class were not derived from MailManager.The event pattern also requires that the delegate definition and the callback method name the EventArgs-derived parameter e.
Tools that spit out source code (such as Microsoft Visual Studio) also know to call the parameter e.
(3)the event pattern requires all event handlers to have a return type of void.
This is necessary because raising an event might call several callback methods, and there is no way to get the return values from all of them.
Having a return type of void doesn’t allow the callbacks to return a value.
Unfortunately, there are some event handlers in the FCL, such as ResolveEventHandler, that did not follow Microsoft’s own prescribed pattern because it returns an object of type Assembly.
(4)Raising an Event in a Thread-Safe Way

The problem with the OnNewMail method is that the thread could see that NewMail is not null, and then, just before invoking NewMail, another thread could remove a delegate from the chain making NewMail null, resulting in a NullReferenceException being thrown
优化:理论正确,但编译器优化之后还是错误的

it doesn’t matter if another threadchanges NewMail after the assignment to temp. but,Remember that delegates are immutable and this is why this technique works in theory.
However, what a lot of developers don’t realize is that this code could be optimized by the compiler to remove the local temp variable entirely.
If this happens, this version of the code is identical to the first version, so a NullReferenceException is still possible.
优化:真正正确

Volatile.Read forces NewMail to be read at the point of the call and the reference really has to be copied to the temp variable now.
Then, temp will be invoked only if it is not null.
the just-in-time (JIT) compiler is aware of this pattern and it knows not to optimize away the local temp variable.
Specifically, all of Microsoft’s JIT compilers respect the invariant of not introducing new reads to heap memory and therefore, caching a reference in a local variable ensures that the heap reference is accessed only once.
events are mostly used in singlethreaded scenarios (Windows Presentation Foundation and Windows Store apps) and so thread safety is not an issue anyway.
It is very important to note that due to this thread race condition, it is also possible that a method will be invoked after it has been removed from the event’s delegate chain.
2.How the Compiler Implements an Event
public event EventHandler<NewMailEventArgs> NewMail;
compiling


1.The first construct is simply a field of the appropriate delegate type. This field is a reference to the head of a list of delegates that will be notified when this event occurs.
This field is initialized to null, meaning that no listeners have registered interest in the event
field, NewMail in this example, is always private even though the original line of source code defines the event as public.to prevent code outside the defining class from manipulating it improperly
2.If you attempt to remove a method that was never added, then Delegate’s Remove method internally does nothing. That is, you get no exception or warning of any type; the event’s collection of methods remains unchanged.
3.The add and remove methods use a well-known pattern to update a value in a thread-safe way
4.when you define an event in a type, the accessibility of the event determines what code can register and unregister interest in the event, but only the type itself can ever access the delegate field directly
6.compilers also emit an event definition entry into the managed assembly’s metadata.
This entry contains some flags and the underlying delegate type, and refers to the add and remove accessor methods.
This information exists simply to draw an association between the abstract concept of an “event” and its accessor methods.
Compilers and other tools can use this metadata
and this information can also be obtained by using the System.Reflection.EventInfo class.
However, the CLR itself doesn’t use this metadata information and requires only the accessor methods at run time.
3.Designing a Type That Listens for an Event
how to define a type that uses an event provided by another type


1. When the email application initializes, it would first construct a MailManager object and save the reference to this object in a variable. Then the application would construct a Fax object, passing the reference to the MailManager object as a parameter
2.mm.NewMail += FaxMsg;
compiling
mm.add_NewMail(new EventHandler<NewMailEventArgs>(this.FaxMsg));
the C# compiler is generating code that will construct an EventHandler<NewMailEventArgs> delegate object that wraps the Fax class’s FaxMsg method
3.As long as an object has registered one of its methods with an event, the object can’t be garbage collected.
If your type implements IDisposable’s Dispose method, the implementation should cause it to unregister interest in all events
4.C# requires your code to use the += and -= operators to add and remove delegates from the list.
If you try to call the add or remove method explicitly, the C# compiler produces the CS0571 cannot explicitly call operator or accessor error message.
4.Explicitly Implementing an Event
原因:
The System.Windows.Forms.Control type defines about 70 events. If the Control type implemented the events by allowing the compiler to implicitly generate the add and remove accessor methods and delegate fields, every Control object would have 70 delegate fields in it just for the events!
Because most programmers care about just a few events, an enormous amount of memory would be wasted for each object created from a Control-derived type
the ASP.NET System.Web.UI.Control and the Windows Presentation Foundation (WPF) System.Windows.UIElement type also offer many events that most programmers do not use.
how the C# compiler allows a class developer to explicitly implement an event, allowing the developer to control how the add and remove methods manipulate the callback delegates.
1.To efficiently store event delegates, each object that exposes events will maintain a collection (usually a dictionary) with some sort of event identifier as the key and a delegate list as the value. collection store events that developer interested
(1).When the object needs to raise an event, the event identifier is looked up in the collection.
If the event identifier is in the collection, the delegate list associated with the event identifier is invoked.
Implementing this design pattern is the responsibility of the developer who is designing the type that defines the events;
the developer using the type has no idea how the events are implemented internally.


2.show a class that uses my EventSet class. This class has a field that refers to an EventSet object, and each of this class’s events is explicitly implemented


3.uses the TypeWithLotsOfEvents type can’t tell whether the events have been implemented implicitly by the compiler or explicitly by the developer.They just register the events by using normal syntax.

其他知识:
1.The FCL defines a type, System.Windows.EventHandlersStore, which does essentially the same thing as my EventSet class.
Various WPF types use the EventHandlersStore type internally to maintain their sparse set of events. You’re certainly welcome to use the FCL’s EventHandlersStore type if you’d like.
The big difference between the EventHandlersStore type and my EventSet type is that EventHandlersStore doesn’t offer any thread-safe way to access the events;
you would have to implement your own thread-safe wrapper around the EventHandlersStore collection if you need to do this.
11.Events的更多相关文章
- python学习笔记-进程线程
1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...
- python学习道路(day10note)(线程,进程)
1.计算机的发展史 看alex的博客吧,了解一下可以了 2.线程与GIL简介 #线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷 ...
- 服务器cpu负载过高问题排查
https://blog.csdn.net/MrZhangXL/article/details/77711996 第一步 :执行top命令,查出当前机器线程情况 top - 09:14:36 up 1 ...
- perf之sched
如果你对你的进程的响应时间极其苛刻,有一天你发现你的进程响应时间变慢了,而恰好这个机器上也有其他的进程在跟你的进程争用CPU,你想看看你的进程被内核调度的情况,那么你需要用perf-sched工具. ...
- 三种系统监控工具对比:top vs Htop vs Glances
首先启用 EPEL Repository: yum -y install epel-release 启用 EPEL Repository 後, 可以用 yum 直接安裝 Htop: yum -y in ...
- Perf -- Linux下的系统性能调优工具,第 2 部分 特殊用法以及内核调优示例
https://www.ibm.com/developerworks/cn/linux/l-cn-perf2/ 本文内容简介 之前介绍了 perf 最常见的一些用法,关注于 Linux 系统上应用程序 ...
- zigbee 中 OSAL 事件传递机制和消息传递机制
一.概述 OSAL (Operating System Abstraction Layer) ,翻译为"操作系统抽象层". OSAL 就是一种支持多任务运行的系统资源分配机制.OS ...
- 新手学分布式-动态修改Nginx配置的一些想法
本人是分布式的新手,在实际工作中遇到了需要动态修改nginx的需求,因此写下实现过程中的想法.Nginx功能强大且灵活,所以这些权当抛砖引玉,希望可以得到大家的讨论和指点.(具体代码在 https:/ ...
- 实现Mac主机上的Docker容器中的图形界面显示(运行GUI应用)
我有一个需求: 一方面,我需要在 Docker 容器环境下运行应用(因为有些环境在 Mac 下很难安装配置,并且希望环境干净隔离). 另一方面,容器中的应用又需要进行图形界面的显示. 由于 Docke ...
随机推荐
- 想学习一下CSS函数
好像原来都是用前后端代码实现的功能,如今CSS3已经吸纳为标准,使用简单的选择器就可以实现了.
- SQL删除重复数据方法
例如: id name value 1 a pp 2 a ...
- Linux 封闭端口和安全
两种方法: 1.停掉没用的服务,关闭端口监听 2.用 iptables 封闭端口 ######################################## 1.查看端口和占用服务 netsta ...
- Delphi 中将一些 Dll等生成资源文件打包成一个独立的EXE程序方法步骤
资源文件一般为扩展名为res的文件,其自带的资源编译工具BRCC32.EXE(位于/Delphi/BIN目录下) 1.编写rc脚本文本 用记事本或其它文本编辑器编写一个扩展名为rc的文件,格式分别为在 ...
- Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】
本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...
- 数据库日期格式为int型时存取格式
存入当前日期:time() 取出并转化为日期格式:date('Y-m-d H:i:s',strtotime($time)); 最好在前面加上这句: date_default_timezone_set( ...
- SELECT INTO和INSERT INTO SELECT
--自动创建了target_table表,并复制source_table表的数据到target_table select name,age into target_table from source_ ...
- linux异步通信之epoll【转】
转自:http://www.cnblogs.com/snake-hand/archive/2012/08/13/2636229.html 1.简介 epoll是linux提供的一种异步的I/O通知方式 ...
- grep DEMO
测试数据: [xiluhua@vm-xiluhua][~]$ cat msn.txt aaa bbb bbb ccc ccc ddd bbb eee aaa ccc bbb sss [xiluhua@ ...
- Java获取字符串编码方式
直接下载吧: http://files.cnblogs.com/files/xiluhua/BytesEncodingDetectTool.rar