C#基礎教程:事件
事件定義的時候,可以使用add和remove關鍵字來自定義事件處理函式的新增與移除功能。例如,可以在新增和移除之前,使用lock關鍵字實現執行緒同步。雖然MethodImplAttribute會用當前類的物件作為同步物件實現執行緒同步,但當物件需要向外界公佈多個事件的時候,這樣做會產生效率問題。比如:物件A向外界公佈了E1、E2兩個事件,訂閱方O1使用+=運算子試圖訂閱E1事件;訂閱方O2也使用+=運算子試圖訂閱E2事件。假設這兩個訂閱操作同時進行,那麼無論誰先搶到訂閱權,另一個操作不得不等待,直到前一個訂閱操作成功完成。這是因為,MethodImplAttribute會將A用作執行緒同步的鎖定物件;對於O1和O2而言,在訂閱事件的時候,是共用同一個鎖定物件的。MethodImplAttribute另一個問題在於,如果A是一個值物件,那麼就根本沒法使用A作為鎖定物件,因為A根本沒有“同步索引”,因此你就無法使用多執行緒去同步使用這樣的物件,即使是使用了MethodImplAttribute,也只不過是一個擺設。
仍然以EventDemo專案為例,我們將該案例中Server類的事件定義部分稍作改動,將其改為下面的形式:
view plaincopy to clipboardprint?
private readonly object syncRoot_Started = new object();
private readonly object syncRoot_Stopped = new object();
private ServerEventHandler m_StartedEventHandler;
private ServerEventHandler m_StoppedEventHandler;
///
/// 定義一個事件,當伺服器正常啟動後,觸發該事件
///
public event ServerEventHandler Started
{
add
{
lock (syncRoot_Started)
{
m_StartedEventHandler += value;
}
}
remove
{
lock (syncRoot_Started)
{
m_StartedEventHandler -= value;
}
}
}
///
/// 定義一個事件,當伺服器正常結束後,觸發該事件
///
public event ServerEventHandler Stopped
{
add
{
lock (syncRoot_Stopped)
{
m_StoppedEventHandler += value;
}
}
remove
{
lock (syncRoot_Stopped)
{
m_StoppedEventHandler -= value;
}
}
}
protected virtual void DoStarted(object sender, ServerEventArgs e)
{
if (m_StartedEventHandler != null)
m_StartedEventHandler(sender, e);
}
protected virtual void DoStopped(object sender, ServerEventArgs e)
{
if (m_StoppedEventHandler != null)
m_StoppedEventHandler(sender, e);
}
現在,我們新加入了用於同步的物件syncRoot_Started和syncRoot_Stopped,它們被定義為Server的私有隻讀成員;在定義事件處理列表新增與移除的邏輯裡,使用lock關鍵字實現執行緒同步,確保對於同一個事件的呼叫列表,在同一時刻只有一個執行緒對其進行操作。在前面的事件實現過程中,由於我們使用預設的add和remove方法,因此C#編譯器會自動生成一個類似於上述程式碼中m_StartedEventHandler、m_StoppedEventHandler的私有成員,而在自定義的實現方式裡,開發人員必須手工新增這樣的私有成員。
C#中的屬性可以是隻包含get的只讀屬性,可以是隻包含set的只寫屬性,還可以是既包含get又包含set的讀寫屬性;而event的定義不同,add和remove必須成對出現。
還有一種情況下,會用add和remove來自定義事件的處理過程的新增與移除,就是當某個物件需要向外界公佈多個事件時,此時,沒有必要針對每個事件都定義一個私有成員,具體做法是,在類中定義一個集合(比如字典),在add中,向集合新增事件處理過程,而在remove中,將事件處理過程從集合中移除。我們再次改造上述例項,透過使用System.ComponentModel.EventHandlerList類來實現這樣的效果:
view plaincopy to clipboardprint?
private readonly object syncRoot_Started = new object();
private readonly object syncRoot_Stopped = new object();
//private ServerEventHandler m_StartedEventHandler;
//private ServerEventHandler m_StoppedEventHandler;
private readonly object eventStarted = new object();
private readonly object eventStopped = new object();
private EventHandlerList eventHandlerList = new EventHandlerList();
///
/// 定義一個事件,當伺服器正常啟動後,觸發該事件
///
public event ServerEventHandler Started
{
add
{
lock (syncRoot_Started)
{
// m_StartedEventHandler += value;
eventHandlerList.AddHandler(eventStarted, value);
}
}
remove
{
lock (syncRoot_Started)
{
// m_StartedEventHandler -= value;
eventHandlerList.RemoveHandler(eventStarted, value);
}
}
}
///
/// 定義一個事件,當伺服器正常結束後,觸發該事件
///
public event ServerEventHandler Stopped
{
add
{
lock (syncRoot_Stopped)
{
// m_StoppedEventHandler += value;
eventHandlerList.AddHandler(eventStopped, value);
}
}
remove
{
lock (syncRoot_Stopped)
{
// m_StoppedEventHandler -= value;
eventHandlerList.RemoveHandler(eventStopped, value);
}
}
}
protected virtual void DoStarted(object sender, ServerEventArgs e)
{
ServerEventHandler startedHandler = (ServerEventHandler) eventHandlerList[eventStarted];
if (startedHandler != null)
startedHandler(sender, e);
}
protected virtual void DoStopped(object sender, ServerEventArgs e)
{
ServerEventHandler stoppedHandler = (ServerEventHandler) eventHandlerList[eventStopped];
if (stoppedHandler != null)
stoppedHandler(sender, e);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/755/viewspace-2801046/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- c#基礎教程C#
- C#基礎系列--C#中委託與事件(三)C#事件
- C#基礎系列--C#中委託與事件(一)C#事件
- c#圖解教程 類基礎C#圖解
- C#程式設計基礎入門教程pdfC#程式設計
- JS基礎 ---事件JS事件
- c#基礎C#
- C#基礎——abstractC#
- c#基礎-基礎-16.stringC#
- NMAP 基礎教程
- MotionLayout 基礎教程
- typora基礎教程
- tkinter 基礎教程
- jQuery基礎教程jQuery
- Git基礎教程Git
- Memcache基礎教程
- C#基礎系列:再也不用擔心面試官問我“事件”了C#面試事件
- javascript事件基礎知識JavaScript事件
- JavaScript基礎之事件eventJavaScript事件
- C#基礎語法C#
- Go 基礎教程--2-基礎知識Go
- AIX基礎教程(zt)AI
- Python基礎教程Python
- EasyExcel基礎使用教程Excel
- Teradata基礎教程
- Django 基礎教程 - 模板Django
- JavaScript 基礎教程 (轉)JavaScript
- 【Matlab】基礎教程Matlab
- 【重溫基礎】20.事件事件
- 前端基礎 — Web事件總結前端Web事件
- JS基礎_滾輪的事件JS事件
- node基礎(1)---eventloop事件環OOP事件
- javascript基礎(事件物件)(三十一)JavaScript事件物件
- C#基礎之介面(6)C#
- MongoDB for C#基礎入門MongoDBC#
- C#字串基礎學習C#字串
- C#基礎概念面試題C#面試題
- C#面試基礎問題C#面試