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的更多相关文章

  1. python学习笔记-进程线程

    1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...

  2. python学习道路(day10note)(线程,进程)

    1.计算机的发展史 看alex的博客吧,了解一下可以了 2.线程与GIL简介 #线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷 ...

  3. 服务器cpu负载过高问题排查

    https://blog.csdn.net/MrZhangXL/article/details/77711996 第一步 :执行top命令,查出当前机器线程情况 top - 09:14:36 up 1 ...

  4. perf之sched

    如果你对你的进程的响应时间极其苛刻,有一天你发现你的进程响应时间变慢了,而恰好这个机器上也有其他的进程在跟你的进程争用CPU,你想看看你的进程被内核调度的情况,那么你需要用perf-sched工具. ...

  5. 三种系统监控工具对比:top vs Htop vs Glances

    首先启用 EPEL Repository: yum -y install epel-release 启用 EPEL Repository 後, 可以用 yum 直接安裝 Htop: yum -y in ...

  6. Perf -- Linux下的系统性能调优工具,第 2 部分 特殊用法以及内核调优示例

    https://www.ibm.com/developerworks/cn/linux/l-cn-perf2/ 本文内容简介 之前介绍了 perf 最常见的一些用法,关注于 Linux 系统上应用程序 ...

  7. zigbee 中 OSAL 事件传递机制和消息传递机制

    一.概述 OSAL (Operating System Abstraction Layer) ,翻译为"操作系统抽象层". OSAL 就是一种支持多任务运行的系统资源分配机制.OS ...

  8. 新手学分布式-动态修改Nginx配置的一些想法

    本人是分布式的新手,在实际工作中遇到了需要动态修改nginx的需求,因此写下实现过程中的想法.Nginx功能强大且灵活,所以这些权当抛砖引玉,希望可以得到大家的讨论和指点.(具体代码在 https:/ ...

  9. 实现Mac主机上的Docker容器中的图形界面显示(运行GUI应用)

    我有一个需求: 一方面,我需要在 Docker 容器环境下运行应用(因为有些环境在 Mac 下很难安装配置,并且希望环境干净隔离). 另一方面,容器中的应用又需要进行图形界面的显示. 由于 Docke ...

随机推荐

  1. 在CentOS 6 32/64 上安装 PPTP 方式 VPN 服务

    网上有很多步骤, 讲了很多步骤,废话, 其实不如直接看代码, 而且也能直接运行,快速安装: rm -f /etc/pptpd.conf rm -f /etc/ppp arch=`uname -m` # ...

  2. 161201、常用 SQL Server 规范集锦

    常见的字段类型选择   1.字符类型建议采用varchar/nvarchar数据类型 2.金额货币建议采用money数据类型 3.科学计数建议采用numeric数据类型 4.自增长标识建议采用bigi ...

  3. 阿里BCG重磅报告《人工智能,未来致胜之道》

    阿里BCG重磅报告<人工智能,未来致胜之道> 阿里云研究中心.波士顿咨询公司以及Alibaba Innovation Ventures合作共同推出的<人工智能:未来制胜之道>这 ...

  4. Thinkphp用exp表达式执行mysql语句,查询某字段不为空is not null,自动增值

    Thinkphp用exp表达式执行mysql语句,查询某字段不为空is not null,自动增值 Thinkphp 的文档经常不够完整的表达MYSQL的各种组合,is not null在thinkp ...

  5. 进度条,随机数---demo笔记【原创】

    本人学习笔记,参考网上代码完成 makefile TEST_OBJ := rng_app MAKEOPT := ARCH=arm CROSS_COMPILE=arm-none-linux-gnueab ...

  6. (个人)读取A.CSV修改它的某列,写入B.CSV

    #!/usr/bin/perl -wuse strict;use warnings;use Tie::File; open(IN_FILE,"<E:/Hzj_works/test1.c ...

  7. class id 区别

    [1].id是唯一的,一个元素只能有一个,不能重复class可以重复 <div> <img src="" width="100%"/> ...

  8. hdwiki 编码规范

    编码规范         命名规范 1.1.主要的目录 control 里面是控制类 ,前台命名为something.php,则后台对应的是admin_+前台名称,名称应选有意义的英文单词,例如 前台 ...

  9. 获取手机IMEI 号和 IP

    没什么可说的,直接上代码: public class PhoneStateCodeUtils { /** * 获取手机imei串号 */ public static String getImei(Co ...

  10. <<构建之法>>略读感想

    经过对构建之法这本书的快速阅读和学习,我有以下疑问. 1.对软件工程来说是应该更注重结果和功能的实现还是更注重代码的易读和完整? 2.应该怎样平衡不同用户的不同需求以达到使大多数人满意的目的? 3.应 ...