C 基礎 事件(四)

2022-01-20 19:31:57 字數 3312 閱讀 6488

事件定義的時候,可以使用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 = 

newobject

();   

private

readonly

object

syncroot_stopped = 

newobject

();   

private

servereventhandler m_startedeventhandler;   

private

servereventhandler m_stoppedeventhandler;   

/// 

/// 定義乙個事件,當伺服器正常啟動後,觸發該事件

/// 

public

event

servereventhandler started   

}   

remove   

}   

}   

/// 

/// 定義乙個事件,當伺服器正常結束後,觸發該事件

/// 

public

event

servereventhandler stopped   

}   

remove   

}   

}   

protected

virtual

void

dostarted(

object

sender, servereventargs e)   

protected

virtual

void

dostopped(

object

sender, servereventargs 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 = 

newobject

();   

private

readonly

object

syncroot_stopped = 

newobject

();   

//private servereventhandler m_startedeventhandler;

//private servereventhandler m_stoppedeventhandler;

private

readonly

object

eventstarted = 

newobject

();   

private

readonly

object

eventstopped = 

newobject

();   

private

eventhandlerlist eventhandlerlist = 

neweventhandlerlist();   

/// 

/// 定義乙個事件,當伺服器正常啟動後,觸發該事件

/// 

public

event

servereventhandler started   

}   

remove   

}   

}   

/// 

/// 定義乙個事件,當伺服器正常結束後,觸發該事件

/// 

public

event

servereventhandler stopped   

}   

remove   

}   

}   

protected

virtual

void

dostarted(

object

sender, servereventargs e)   

protected

virtual

void

dostopped(

object

sender, servereventargs e)   

C 基礎知識系列 專題四 事件揭秘

引言 前面幾個專題對委託進行了詳細的介紹的,然後我們在編寫 過程中經常會聽到 事件 這個概念的,尤其是寫ui的時候,當我們點選乙個按鈕後vs就會自動幫我們生成一些後台的 然後我們就只需要在click方法裡面寫 就可以,所以可能有些剛接觸c 的朋友就覺得這樣很理所當然的,也沒有去思考這是為什麼的,為什...

C 事件驅動基礎

事件 事件是物件傳送的訊息,以發訊號通知操作的發生。事件可以由使用者互動引起,例如單擊按鈕,也可能是由某些其他程式的邏輯引發,例如更改的屬性值。引發事件的物件稱為event sender 事件傳送方不知道哪個物件或方法將接收到 處理 它引發的事件。事件通常是事件傳送方,例如click事件是butto...

JS基礎學習四 繫結事件

b 新增事件 b ie attachevent other addeventlistener var button document.getelementbyid buttonid if button.addeventlistener else if button.attachevent b 刪除事...