C# 事件機制
轉自:http://www.cnblogs.com/donghaiyiyu/archive/2007/07/29/828738.html
在所有關於C#事件機制的介紹中,我更傾向於釋出者/訂閱者(Publisher/Subscriber)這種描述。理解事件機制並不是一件容易的事情,它所涉及的思想值得我們好好去研究。
本文資源來自《C#與.NET技術平臺實戰演練》——中國青年出版社
談到事件,我們涉及到兩個角色:事件釋出者(Publisher)和事件訂閱者(Scriber),也可以說是事件傳送者(Sender)和事件接收者(Receiver)的關係。舉個例子來說,市面上目前有許多雜誌,雜誌的種類也很多。而我只對其中的某些感興趣,那麼我就可以向雜誌發行商提出訂閱。之後,每當雜誌發行時,我就會收到我在雜誌發行商那兒訂閱的雜誌。在這個關係中,雜誌發行商就相當於事件發行者,而我就是事件訂閱者。每當雜誌發行時,就觸發了一個發行事件。
用物件導向的語言解釋,這兩者的意義如下:
事件發行者(Publisher)
它是一個物件,且會維護自身的狀態資訊。每當狀態資訊發生變動時,便觸發一個事件,並通知所有的事件訂閱者。對於雜誌發行商來說,每本雜誌都有自己的資訊在裡面,當雜誌發行時,我要通知訂閱該雜誌的人:雜誌已經發行啦,請注意查收!
事件接收者(Receiver)
這個物件要註冊它感興趣的物件,也就是訂閱它自己喜歡的雜誌啦。另外,這個物件通常要提供一個事件處理方法,在事件發行者觸發一個事件後,會自動執行這個方法。對於上面所舉的例子來說,也就是我收到雜誌後要做什麼事情,比如,你可以滿世界地大喊:我收到雜誌啦!也可以將雜誌收藏起來慢慢欣賞,具體怎麼實現完全取決你自己的喜好。
以下是.NET事件處理機制的模型:
下面給一個簡單的例子,用以闡述事件的思想:
2using System.Collections.Generic;
3using System.Text;
4
5namespace EventDemo
6{
7 public delegate void SalaryCompute(); //宣告一個代理類
8
9 public class Employee
10 {
11 public event SalaryCompute OnSalaryCompute; //定義事件,將其與代理繫結
12
13 public virtual void FireEvent() //觸發事件的方法
14 {
15 if (OnSalaryCompute != null)
16 {
17 OnSalaryCompute(); //觸發事件
18 }
19 }
20 }
21
22 public class HumanResource
23 {
24 public void SalaryHandler() //事件處理函式
25 {
26 Console.WriteLine("Salary"); //只是列印一行字而已
27 }
28
29 public static void Main()
30 {
31 Employee ep = new Employee();
32 HumanResource hr = new HumanResource();
33 ep.OnSalaryCompute+=new SalaryCompute(hr.SalaryHandler); //註冊
34 ep.FireEvent(); //觸發事件
35 Console.Read();
36 }
37 }
38}
39
與之相對應,HumanResource類則相當於一個事件訂閱者(Subscriber),它定義了一個事件處理函式(SalaryHandler()),並用+=將其與事件聯絡起來,從而使事件觸發的時候能夠呼叫我這個方法(在本例中也就是列印一行字啦)。值得注意的一點是,事件處理函式的方法簽名要與代理的方法簽名相同,這是非常重要的一點。
下面將這個例子改造一下,事件引數資訊,用以完善事件機制。
2using System.Collections.Generic;
3using System.Text;
4using System.Threading;
5
6namespace EventDemo
7{
8 public delegate void SalaryCompute(object sender,MyEventArgs e); //宣告一個代理類
9
10 public class Employee
11 {
12 public event SalaryCompute OnSalaryCompute; //定義事件,將其與代理繫結
13
14 public virtual void FireEvent(MyEventArgs e) //觸發事件的方法
15 {
16 if (OnSalaryCompute != null)
17 {
18 OnSalaryCompute(this,e); //觸發事件
19 }
20 }
21 }
22
23 public class MyEventArgs : EventArgs //定義事件引數類
24 {
25 public readonly double _salary;
26 public MyEventArgs(double salary)
27 {
28 this._salary = salary;
29 }
30 }
31
32 public class HumanResource
33 {
34 public void SalaryHandler(object sender,MyEventArgs e) //事件處理函式,其簽名應與代理簽名相同
35 {
36 Console.WriteLine("Salary is {0}",e._salary); //只是列印一行字而已
37 }
38
39 public static void Main()
40 {
41 Employee ep = new Employee();
42 HumanResource hr = new HumanResource();
43 MyEventArgs e = new MyEventArgs(123.40);
44 ep.OnSalaryCompute+=new SalaryCompute(hr.SalaryHandler); //註冊
45 for (; ; )
46 {
47 Thread.Sleep(1000); //讓程式“睡”一秒
48 ep.FireEvent(e); //觸發事件
49 }
50 //Console.Read();
51 }
52 }
53}
54
這個例子很有意思,它一秒鐘自動觸發事件一次,比上一個例子更能解釋事件的機制,對吧?在這個例子中,我們要注意的一個地方就是事件處理函式的簽名要和代理的簽名一致
事件與委託的區別:
事件就是一個狹義的委託,也就是事件是一個用於事件驅動模型的專用委託. 通俗的講,委託你可以在客戶程式碼中直接呼叫委託來激發委託指向的函式,而事件不可以,事件的觸發只能由服務程式碼自己觸發 也就是說在你的程式碼裡委託你不但可以安排誰是它的呼叫函式,還可以直接呼叫它,而事件不能直接呼叫,只能通過某些操作觸發 你可以理解事件就是一個或多個委託,此話應該有誤的吧,事件可以有多個事件處理函式,委託同樣也可以是個多播委託
相關文章
- C#事件處理機制C#事件
- 淺談JS事件機制與React事件機制JS事件React
- DOM事件機制事件
- react事件機制React事件
- redis事件機制Redis事件
- qt事件機制QT事件
- Redis的事件機制Redis事件
- View事件機制分析View事件
- Android 事件機制Android事件
- JavaScript執行緒機制與事件機制JavaScript執行緒事件
- Javascript事件模型系列(二)事件的捕獲-冒泡機制及事件委託機制JavaScript事件模型
- JS的事件物件與事件機制JS事件物件
- Redis 事件機制詳解Redis事件
- JS 事件機制 Event LoopJS事件OOP
- 【React深入】React事件機制React事件
- JavaScript事件迴圈機制JavaScript事件
- Qt 事件機制 學習QT事件
- JavaScript 事件迴圈機制JavaScript事件
- View事件分發機制View事件
- Remoting事件機制續REM事件
- Mutexes機制及其等待事件Mutex事件
- jQuery的事件機制,事件物件介紹,外掛機制,多庫共存,each()jQuery事件物件
- 【C#】:淺談反射機制C#反射
- 深入理解DOM事件機制事件
- javascript事件迴圈機制EventLoopJavaScript事件OOP
- React原始碼分析 – 事件機制React原始碼事件
- View事件分發機制分析View事件
- Android事件分發機制Android事件
- javascript之事件迴圈機制JavaScript事件
- redis的事件處理機制Redis事件
- js--事件迴圈機制JS事件
- Spring事件機制詳解Spring事件
- Java——事件處理機制概要Java事件
- React原始碼分析 - 事件機制React原始碼事件
- WebSocket的事件觸發機制Web事件
- 知乎 node事件機制 轉載事件
- vue原始碼解析-事件機制Vue原始碼事件
- Android事件傳遞機制Android事件