事件是對象發送的消息,以發信號通知操作的發生。操作可能是由用戶交互(例如鼠標單擊)引起的,也可能是由某些其他的程序邏輯觸發的。引發(觸發)事件的對象叫做事件發送方。捕獲事件並對其作出響應的對象叫做事件接收方。
在事件通信中,事件發送方類不知道哪個對象或方法將接收到(處理)它引發的事件。所需要的是在源和接收方之間存在一個媒介(或類似指針的機制)。.Net Framework 定義了一個特殊的類型(Delegate),該類型提供函數指針的功能。
與其他的類不同,委托類具有一個簽名,並且它只能對與其簽名匹配的方法進行引用。這樣,委托就等效於一個類型安全函數指針或一個回調。
C#中使用事件需要的步驟:
創建一個委托
將創建的委托與特定事件關聯(.Net類庫中的很多事件都是已經定制好的,所以他們也就有相應的一個委托,在編寫關聯事件處理程序--也就是當有事件發生時我們要執行的方法的時候我們需要和這個委托有相同的簽名)
編寫事件處理程序
利用編寫的事件處理程序生成一個委托實例
把這個委托實例添加到產生事件對象的事件列表中去,這個過程又叫訂閱事件
C#中事件產生和實現的流程:
定義A為產生事件的實例,a為A產生的一個事件
定義B為接收事件的實例,b為處理事件的方法
A由於用戶(程序編寫者或程序使用者)或者系統產生一個a事件(例如點擊一個Button,產生一個Click事件)
A通過事件列表中的委托對象將這個事件通知給B
B接到一個事件通知(實際是B.b利用委托來實現事件的接收)
調用B.b方法完成事件處理
下面給出《C#入門經典》的例子,並做一定的解釋:
//====================Connection.cs===========
//事件定義,也就是上面提到的A
//============================================
using System;
using System.Timers;
namespace Ch12Ex02
{
/// <summary>
/// Connection 的摘要說明。
/// </summary>
///
public delegate void MessageHandler(string messageText);//創建一個委托---步驟1
public class Connection
{
public event MessageHandler MessageArrived;//將創建的委托和特定事件關聯,在這裡特定的事件為MessageArrived ---步驟2*/
/*上面這語句值得注意的地方是 MessageArrived方法被關聯到MessageHandler上後,以後消息的傳遞就通過MessageHandler這個委托來實現,所以如果要能接收這個消息,就必須能支持MessageHandler這個委托,也就是要有一個和委托一樣的簽名
private Timer pollTimer;
public Connection()
{
//
// TODO: 在此處添加構造函數邏輯
//
pollTimer=new Timer(100);
pollTimer.Elapsed+=new ElapsedEventHandler(CheckForMessage);
}
public void Connect()
{
pollTimer.Start();
}
public void Disconnect()
{
pollTimer.Stop();
}
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!
}
}
}
}
//====================Display.cs===========
//接收事件的類,也就是上面提到的B
//=========================================
using System;
namespace Ch12Ex02
{
/// <summary>
/// Display 的摘要說明。
/// </summary>
public class Display
{
public Display()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
public void DisplayMessage(string message) //a事件的最終處理函數,即上面的B.b,在main函數中,我們會使用本函數實現一個委托實例,並且添加到A的MessageArrived事件列表中--步驟3
{
Console.WriteLine("Message Arrived:{0}",message);
}
}
}
//====================Class1.cs=================
//一個控制台可執行類,主要是使用上面兩個類的實例
//==============================================
using System;
namespace Ch12Ex02
{
/// <summary>
/// Class1 的摘要說明。
/// </summary>
class Class1
{
/// <summary>
/// 應用程序的主入口點。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此處添加代碼以啟動應用程序
//
Connection myConnection=new Connection();
Display myDisplay=new Display();
myConnection.MessageArrived+=new MessageHandler(myDisplay.DisplayMessage);//把委托添加到當前A的事件列表中----步驟4和步驟5
myConnection.Connect();
Console.ReadLine();
}
}
}
值得注意的代碼:
public delegate void MessageHandler(string messageText);//委托定義
public event MessageHandler MessageArrived;//定義一個事件,並且關聯到一個委托上
myConnection.MessageArrived+=new MessageHandler(myDisplay.DisplayMessage);//產生一個委托實例,並通過+=運算符號添加到事件列表中 +=運算符號在這裡非常的有用