我来自唐朝
事件的简单解释:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发(触发)事件的对象叫做事件发送方。捕获事件并对其作出响应的对象叫做事件接收方。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
在事件通信中,事件发送方类不知道哪个对象或方法将接收到(处理)它引发的事件。所需要的是在源和接收方之间存在一个媒介(或类似指针的机制)。.NET Framework 定义了一个特殊的类型(Delegate),该类型提供函数指针的功能。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用。这样,委托就等效于一个类型安全函数指针或一个回调。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
C#中使用事件需要的步骤:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
创建一个委托
将创建的委托与特定事件关联(.Net类库中的很多事件都是已经定制好的,所以他们也就有相应的一个委托,在编写关联事件处理程序--也就是当有事件发生时我们要执行的方法的时候我们需要和这个委托有相同的签名)
编写事件处理程序
利用编写的事件处理程序生成一个委托实例
把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件
C#中事件产生和实现的流程:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
定义A为产生事件的实例,a为A产生的一个事件
定义B为接收事件的实例,b为处理事件的方法
A由于用户(程序编写者或程序使用者)或者系统产生一个a事件(例如点击一个Button,产生一个Click事件)
A通过事件列表中的委托对象将这个事件通知给B
B接到一个事件通知(实际是B.b利用委托来实现事件的接收)
调用B.b方法完成事件处理
下面给出《C#入门经典》的例子,并做一定的解释:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//====================Connection.cs===========
//事件定义,也就是上面提到的A
//============================================
using System;
using System.Timers;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace Ch12Ex02
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// Connection 的摘要说明。
/// </summary>
///
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public delegate void MessageHandler(string messageText);//创建一个委托---步骤1
public class Connection
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
{
public event MessageHandler MessageArrived;//将创建的委托和特定事件关联,在这里特定的事件为MessageArrived ---步骤2*/
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*上面这语句值得注意的地方是 MessageArrived方法被关联到MessageHandler上后,以后消息的传递就通过MessageHandler这个委托来实现,所以如果要能接收这个消息,就必须能支持MessageHandler这个委托,也就是要有一个和委托一样的签名
private Timer pollTimer;
public Connection()
{
//
// TODO: 在此处添加构造函数逻辑
//
pollTimer=new Timer(100);
pollTimer.Elapsed+=new ElapsedEventHandler(CheckForMessage);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Connect()
{
pollTimer.Start();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Disconnect()
{
pollTimer.Stop();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void CheckForMessage(object sender,ElapsedEventArgs e)
{
Console.WriteLine("Check for message.");
Random random=new Random();
if((random.Next(9)==0)&&(MessageArrived!=null))
{
MessageArrived("Hello Mum!");//程序编写者自己产生一个消息,消息的内容为Hello Mum!
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//====================Display.cs===========
//接收事件的类,也就是上面提到的B
//=========================================
using System;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
namespace Ch12Ex02
{
/// <summary>
/// Display 的摘要说明。
/// </summary>
public class Display
{
public Display()
{
//
// TODO: 在此处添加构造函数逻辑
//
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void DisplayMessage(string message) //a事件的最终处理函数,即上面的B.b,在main函数中,我们会使用本函数实现一个委托实例,并且添加到A的MessageArrived事件列表中--步骤3
{
Console.WriteLine("Message Arrived:{0}",message);
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//====================Class1.cs=================
//一个控制台可执行类,主要是使用上面两个类的实例
//==============================================
using System;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
namespace Ch12Ex02
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Connection myConnection=new Connection();
Display myDisplay=new Display();
myConnection.MessageArrived+=new MessageHandler(myDisplay.DisplayMessage);//把委托添加到当前A的事件列表中----步骤4和步骤5
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
myConnection.Connect();
Console.ReadLine();
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
值得注意的代码:
public delegate void MessageHandler(string messageText);//委托定义
public event MessageHandler MessageArrived;//定义一个事件,并且关联到一个委托上
myConnection.MessageArrived+=new MessageHandler(myDisplay.DisplayMessage);//产生一个委托实例,并通过+=运算符号添加到事件列表中 +=运算符号在这里非常的有用
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)