关于委托: https://blog.csdn.net/qq_42672770/article/details/104431161
关于Action: https://blog.csdn.net/qq_42672770/article/details/108487709
事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。
C# 中使用事件机制实现线程间的通信。
1.事件的定义
给事件下个准确的定义是一个较困难的事,这里我暂且给它定义为:事件是两个对象之间的交互行为,这里关注四个字“两个对象”。不理解不要紧,这样定义本身并不准确。,继续往下看。
事件定义之前先声明一个委托,然后声明一个事件:
2.事件的三要素
学会运用事件,一定要知道事件的三要素:事件拥有者、事件订阅者、事件处理方法。
事件拥有者:也叫事件发布者,个人觉得叫拥有者更方便理解,很显然,谁定义事件谁就是事件的拥有者。具体到代码中也就是哪个类中定义了的事件,那么这个类的实例就是事件的拥有者。
事件订阅者:可理解为“盯着”事件拥有者的某个行为的对象。
事件处理方法:事件触发后要执行的方法。当事件订阅者“发现”事件拥有者的事件被触发时,事件订阅者需要去执行的方法。仔细回味这句话,不难发现事件处理方法是定义在事件订阅者中,在发布者的事件中调用。
事件在类中声明且生成,且通过使用同一个类或其他类中的委托 来关联到 事件处理程序。事件使用 发布-订阅(publisher-subscriber) 模型。
包含事件的类用于发布事件。这被称为 发布器(publisher) 类。
其他接受该事件的类被称为 订阅器(subscriber) 类。
发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。
发布器(publisher)类的对象调用这个事件,并通知其他的对象。
订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。
在发布器(publisher)类中的委托(事件) 调用订阅器(subscriber)类中的方法(或者说是:订阅器中的方法对发布器的委托(事件)进行响应处理)。
事件和委托的联系与区别
从事件的声明,我们可以大致看出事件与委托的关系,事件是委托的特殊实现,事件是建立在对委托的语言支持之上的。
委托是一种类型,事件是委托类型的一个实例,加上了event的权限控制,限制权限,只允许在事件声明类里面去invoke和赋值,不允许外面,甚至子类调用。
用一个简单的例子,来说明一下这种消息传递的机制。有一家三口,妈妈负责做饭,爸爸和孩子负责吃。。。将这三个人,想象成三个类。 妈妈有一个方法,叫做“做饭”。有一个事件,叫做“开饭”。做完饭后,调用开饭事件,发布开饭消息。 爸爸和孩子分别有一个方法,叫做“吃饭”。 将爸爸和孩子的“吃饭”方法,注册到妈妈的“开饭”事件。也就是,订阅妈妈的开饭消息。让妈妈做完饭开饭时,发布吃饭消息时,告诉爸爸和孩子一声。 这种机制就是C#中的,订阅发布。下面我们用代码实现:
//订阅消息
class Program { public static void Main(string[] args) { //实例化对象 Mom mom = new Mom(); Dad dad = new Dad(); Child child = new Child(); //将爸爸和孩子的Eat吃饭方法注册到妈妈的Eat开饭事件 //也就是订阅妈妈开饭的消息 mom.Eat += dad.Eat; mom.Eat += child.Eat; //调用妈妈的Cook事件 mom.Cook(); Console.Write("Press any key to continue . . . "); Console.ReadKey(true); } } ------------------------------------------------------------------
//发布器publisher public class Mom { //定义Eat事件,用于发布吃饭消息 public event Action Eat; public void Cook() { Console.WriteLine("妈妈 : 饭好了"); //饭好了,发布吃饭消息 Eat?.Invoke(); } }
-------------------------------------------------------------------
//订阅器 subscriiber public class Dad { public void Eat() { //爸爸去吃饭 Console.WriteLine("爸爸 : 吃饭了。"); } }
---------------------------------------------------------------------
//订阅器 subscriiber public class Child { public void Eat() { //熊孩子LOL呢,打完再吃 Console.WriteLine("孩子 : 打完这局再吃。"); } }
--------------------------------------------------------------------------
//猫 叫一声 触发一系列后续动作 //多了个 指定动作 正是这个不稳定 封装出去 甩锅 public event Action CatMiaoActionHandler; public void MiaoEvent() { Console.WriteLine("{0} MiaoEvent", this.GetType().Name); this.CatMiaoActionHandler?.Invoke(); Console.WriteLine("*&^&*^*^*(^&*^&*^&*^&*^"); }
CatMiaoActionHandler
Cat cat = new Cat(); cat.CatMiaoActionHandler += new Dog().Wang; cat.CatMiaoActionHandler += new Mouse().Run; cat.CatMiaoActionHandler += new Baby().Cry;
//cat.CatMiaoActionHandler.Invoke(); //cat.CatMiaoActionHandler = null;
cat.CatMiaoActionHandler += new Mother().Wispher; cat.CatMiaoActionHandler += new Brother().Turn; cat.CatMiaoActionHandler += new Father().Roar; cat.CatMiaoActionHandler += new Neighbor().Awake; cat.CatMiaoActionHandler += new Stealer().Hide; cat.MiaoEvent();
cat.MiaoEvent();
事件主要使用三个类:
1. 参数定义类testEventArgs:继承自EventArgs(虽然EventArgs什么也不做)
2. 事件发布类publisher (发布器monitor)
3. 事件侦听类Receiver (订阅器 subscriiber)
using System;
using System.Collections.Generic;
using System.Text;
namespace EventLearn
{
class testArgs:EventArgs
{
public string msg;
public testArgs(string msg)
{
this.msg = msg;
}
}
class Publisher
{
public delegate void delegateHander(object sender, testArgs e);
public event delegateHander pressKey;
public void Run()
{
do
{
Console.WriteLine("Please press any key. Input 'exit' to finish the process!");
string input=Console.ReadLine();
if (input == "exit")
break;
pressKey(this,new testArgs(input));
}
while(true);
}
}
class Receiver
{
public Receiver(Publisher publisher)
{
publisher.pressKey += new Publisher.delegateHander(this.process);
}
public void process(object sender, testArgs e)
{
Console.WriteLine("You have input the string: {0}", e.msg);
}
}
}
下面是主程序:
using System;
using System.Collections.Generic;
using System.Text;
namespace EventLearn
{
class Program
{
static void Main(string[] args)
{
monitor Monitor = new monitor();
Receiver receiver = new Receiver(Monitor);
Monitor.Run();
Console.ReadKey();
}
}
}
参阅:https://blog.csdn.net/weixin_34368949/article/details/85402867