事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些 提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。
C#中使用事件机制实现线程间的通信。
事件的处理需要委托实现来调度事件,所以事件和委托是紧密关联的(耦合性高)
事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。 包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类 被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。
发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义 在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher) 类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。
简单来说就是事件可以为任何一种委托类型提供一种发布/订阅机制。用户可以订阅这 个事件,当发布者触发事件后,所有的订阅者都会收到通知。关键是发布者不知道订阅 者是谁,有多少个订阅者。这样的好处是各个模块可以专心做自己的事,不需要过问其 他模块的事情。
在类的内部声明事件,首先必须声明该事件的委托类型。例如:
public delegate void PrintHandler();
其次,使用 event 关键字声明事件本身:
public event PrintHandler printTest;
上面的代码定义了一个名为 PrintHandler的委托和一个名为 PrintTest 的事件,该事件在生成的时候会调用委托。
然后调用事件,但是只能在声明事件的类中调用事件
- If(printTest!=null)
-
- printTest();
或者
printTest?.Invoke();
这个代码就是判断printTest是否为空,不为空就调用printTest()方法,为空就不执行
最后注册事件,这里声明事件的类为Sample类
Sample.printTest+=实例方法/静态方法
取消订阅的话用-=即可
下面用一段代码演示:
- using System;
-
-
- namespace ConsoleApp1
- {
- //发布器类
- public class Sample
- {
- //声明委托
- public delegate void OrderEventHandler(int x);
- //声明事件
- public event OrderEventHandler order;
- //调用事件
- protected virtual void OnCall()
- {
- order?.Invoke(99);
- }
- public void Start()
- {
- OnCall();
- }
- }
- //订阅器类-1
- public class SubscribEvent1
- {
- public void Print(int x)
- {
- Console.WriteLine("订阅器1,打印数字:"+x);
- }
- }
- //订阅器类-2
- public class SubscribEvent2
- {
- public void Print(int x)
- {
- Console.WriteLine("订阅器2,打印数字:"+x);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- //实例化对象-订阅器类
- SubscribEvent1 se1 = new SubscribEvent1();
- SubscribEvent2 se2 = new SubscribEvent2();
- //实例化对象-发布器类
- Sample sample = new Sample();
- //订阅
- sample.order += se1.Print;
- sample.order += se2.Print;
- //调用事件
- sample.Start();
- Console.ReadLine();
- }
- }
- }
输出结果:
- 订阅器1,打印数字:99
- 订阅器2,打印数字:99
上面我们用发布器类的start函数来调用Oncall函数引发一个事件。通常要引发事件, 应该使名称定义受保护的虚拟方法,protected和virtual使派生类能够覆盖引发事件的 逻辑,但是派生类要始终调用这个受保护的方法,以确保注册的委托接收事件
我们+=来订阅事件,这里订阅了两个方法,当调用事件时这两个方法都会调用
系统内置了两个常用的委托类型 EventHandler 和 EventHandler
如有错漏之处,敬请指正!