正確呼叫事件處理程式

2022-03-05 06:13:14 字數 1340 閱讀 1594

不管是剛接觸 c# 還是已經具有多年開發經驗的大部分人會覺得事件處理很簡單,只需要把事件定義好然後在需要的時候出發它就可以了。其實這種想法是錯誤的,這裡面有很多需要注意的問題。下面這段**是大部分開發人員經常使用的定義事件處理程式的方法。

public

class

eventdemo

}

上面的**中存在乙個嚴重的問題,當在物件上觸發 demo 事件時並沒有關聯的事件處理程式的話,c# 將會用 null 值來表示沒有處理程式與該事件相關聯,進而將會引發 nullreferenceexception 異常。針對這個問題大部分程式設計師會做如下修改:

public

void

demoevent()

}

這種修改方法解決了上述大部分問題,但是還存在乙個隱藏的問題。當有多個執行緒都呼叫這個事件是就會出現執行緒之間相互爭奪,舉個例子來說就是執行緒 a 在執行到if (demo!=null)時發現 demo 不等於 null ,正巧這時執行緒 b 將唯一的事件處理程式解除了訂閱,這時執行緒 a 再呼叫 demo 時事件處理程式已經變為了 null ,進而導致 nullreferenceexception 異常。真多這個問題一些程式設計師又會做如下的修改:

public

void

demoevent()

}

上述這種方法是對等號右側的內容進行了淺拷貝建立了新的引用,使其指向原來的事件處理程式(相當於給事件訂閱者生成了乙個快照),當另乙個程序登出掉事件處理程式時,登出的只是 demo 上所繫結的處理程式,因此當當前的執行緒執行 handler 時是不會出現 nullreferenceexception 異常。這種解決方法是網上所能搜的方法之一,也是絕大部分開發人員所推薦的解決方法。但是這個方法會使**顯得難以理解(尤其是對於開發新手),並且**稍顯冗餘。於是在 c# 6.0 中微軟為我們增加了 null 條件運算子(?.)。null 條件運算子可以安全的呼叫事件處理程式並且使**清晰明了還簡單。首先它會判斷運算子左側的內容是否為 null ,如果是 null 就跳過該語句,反之執行運算子右側的內容。下面我們利用 null 條件運算子對前面的**進行一下改進。

public

void

demoevent()

tip:使用 null 條件運算子有一點需要注意,運算子右側不允許直接出現括號,因此必須使用 invoke 進行觸發事件。每定義乙個委託或者時間編譯器就會生成乙個 invoke 方法。

進行觸發事件。每定義乙個委託或者時間編譯器就會生成乙個 invoke 方法。

c 反射呼叫事件

這裡有個例子 這個例子反射呼叫的是靜態的action。這裡最後寫了三點需要注意的,我覺得很對。委託其實是個字段,要用getfield來獲取 這裡的第乙個答案。stackoverflow裡的,這個就是反射呼叫事件。主要差別在反射的篩選條件 typeof myclass getfields bindin...

用事件呼叫子窗體

今天學到了乙個很有用的知識點,多個窗體呼叫子窗體時,讓子窗體和父窗體降低耦合度。同時子窗體的修改還可以及時反饋到父窗體。如下 為了實現這個例子,你需要準備2個視窗,乙個叫mainform,上面至少需要乙個richtextbox,兩個工具欄按鈕。另乙個叫 mydialog 的子視窗,上面有乙個 tex...

使用事件響應鏈處理事件

我們可以借用responder chain實現了乙個自己的事件傳遞鏈。uiresponder的分類 h檔案 import inte ce uiresponder router void routereventwithname nsstring eventname userinfo nsdiction...