C#学习笔记 事件
什么是事件?
事件是处理事件的对象感兴趣的,能够感知或捕获到一种事物状态的改变。说白了,事件即改变。
中国房价暴涨,对全中国人来说或许是一个事件,因为我们关心,但对其他国家的人来说就不是(除非是想来中国发展)
除非听到了这样一个新闻,开始关注,那么这个变化对他们来说就是一个事件。所以,在这所有的变化中,你能捕获到的,
感兴趣的变化,对你来说,就是一个事件。
那么,把事件这个概念放到程序设计中,又是怎样的呢?其实是一样的。同样的道理,只要机器开着,里面的硬件和软件就会发生状态的改变。
可是对你要编写的代码来讲,并不是所有的这些改变都是事件。你所需要的事件,只是你对这些变化中感兴趣的极小一部分。
你只需要找到你感兴趣的这样一种状态的改变,并且能够捕获它,就可以利用事件处理模型来完成你想做的事情了。
事件,其实是一个消息,WINDOWS 系统是消息驱动的,在C#中称为事件,C#中处理事件是通过委托完成,
必须先理解委托才能更好的理解事件。事件是一个特殊的委托类。
如果设计一个对外提供的事件类型得分这么几步
//第一步:定义一个类型用于存放所有需要发送给事件通知接收者的附加信息
//第二步,定义事件成员
//第三步:定义一个负责引发事件的方法来通知已订阅事件的对象事件已经发生
//第四部,定义一个方法,将输入转化为期望事件
//实现事件
先描述一下使用事件的场景.假设我们希望设计一个电子邮件应用程序.当一个电子邮件消息到达时,用户可能希望该消息转发给传真机(Fax)或者寻呼机(Pager).在构建应用程序结构时,假设我们首先设计一个名为MailManager的类型负责接收发进来的电子邮件消息.然后再为MailManager类型定义一个对外提供的名为NewMail的事件,其他类型(如Fax和Pager)可以订阅该事件.MailManager接收到一个新电子邮件消息时,他会引发该事件,将消息发给每个已订阅的对象.各个对象则以自己期望的方式来处理该消息.
应用程序初始化时,仅需实例化一个MailManager实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //第一步:定义一个类型用于存放所有需要放松给事件通知接送者的附加信息
2 internal class NewMailEventArgs : EventArgs
3 {
4 /// <summary>
5 /// 发送者(m_from) 消息接收者(m_to) 消息主题(m_subject)
6 /// </summary>
7 private readonly string m_from, m_to, m_subject;
8
9 public NewMailEventArgs(string from, string to, string subject)
10 {
11 m_from = from; m_to = to; m_subject = subject;
12 }
13
14 public string From { get { return m_from; } }
15 public string To { get { return m_to; } }
16 public string Subject { get { return m_subject; } }
17 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //第二步,定义事件成员
2 internal class MailManager {
3 public event EventHandler<NewMailEventArgs> NewMail;
4 //第三步:定义一个负责引发事件的方法来通知已订阅事件的对象事件已经发生
5 protected virtual void OnNewMail(NewMailEventArgs e)
6 {
7 //处于线程安全考虑,将委托字段保存到临时字段中
8 //OnNewMail方法定义了一个临时局部变量temp,这个变量将被初始化为事件成员本身
9 //然后变量temp与null比较,如果temp不等于null,那么可以使用它来引发事件,
10 //必须定义这个临时变量就是为了防止一个可能存在线程同步的问题,
11 //如代码中所示,如果不使用变量temp,那么方法将只引用NewMail,这样就有可能
12 //使线程在知道NewMail不为null从而准备引发事件时,另外一个线程将NewMail变为null,这会导致前者
13 //无法引用,如果发生这种情况,视图引发事件将导致抛出NullReferenceException异常
14 EventHandler<NewMailEventArgs> temp = NewMail;
15 if (temp != null)
16 {
17 temp(this, e);
18 }
19 }
20 //第四部,定义一个方法,将输入转化为期望事件
21 public void SimulateNewMail(string from,string to,string subject)
22 {
23 NewMailEventArgs e = new NewMailEventArgs(from, to, subject);
24 OnNewMail(e);
25 }
26
27 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//事件订阅者
internal class Fax
{
public Fax(MailManager mm)
{
mm.NewMail+=FaxMsg;
}
public static void FaxMsg(Object sender,NewMailEventArgs e)
{
Console.WriteLine("Faxing mail message:");
Console.WriteLine(" From={0}, To={1}, Subject={2}",
e.From, e.To, e.Subject);
}
public void Unregister(MailManager mm)
{
mm.NewMail -= FaxMsg;
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //事件订阅者
2 internal class Paper
3 {
4 public Paper(MailManager mm)
5 {
6 mm.NewMail += PaperMsg;
7 }
8 public static void PaperMsg(Object sender, NewMailEventArgs e)
9 {
10 Console.WriteLine("Faxing mail message:");
11 Console.WriteLine(" From={0}, To={1}, Subject={2}",
12 e.From, e.To, e.Subject);
13 }
14 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public sealed class Program {
public static void Main() {
// 构建MailManager对象
MailManager mm = new MailManager();
// 构建传真对象传递给它MailManager对象
Fax fax = new Fax(mm);
// 构建一个传呼机对象传递给它MailManager对象
Pager pager = new Pager(mm);
// 模拟传入邮件
mm.SimulateNewMail("Jeffrey", "Kristin", "I Love You!");
// 强制注销传真对象本身的MailManager
fax.Unregister(mm);
// 模拟传入邮件
mm.SimulateNewMail("Jeffrey", "Mom & Dad", "Happy Birthday.");
}
}