首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

CLR 筆記:事件模式完整實作與線程安全

     編輯:關於.NET

事件核心概念

事件本質為方法。定義事件意味著型別具備三種能力:訂閱、取消訂閱、事件發生時通知已訂閱方法。.NET 事件建立在 Delegate 機制之上,採用 Observer 模式。

10.1 設計提供事件的型別

  1. 定義 EventArgs:繼承 EventArgs,以 EventArgs 結尾,包含私有欄位與唯讀公用屬性。無附加資料時直接使用 EventArgs 基類。
  2. 定義事件成員:public event EventHandler<NewMailEventArgs> NewMail; 等價於委托宣告 delegate void EventHandler<TVEventArgs>(object sender, TVEventArgs e)。sender 為 object 以相容所有型別;e 繼承 EventArgs 保持一致性;事件方法回傳 void 以利事件鏈操作。
  3. 定義引發事件的方法:protected virtual void OnNewMail(NewMailEventArgs e),使用暫存變數 temp 防止線程同步問題。if (temp != null) temp(this, e);
  4. 定義觸發事件的方法:將輸入轉為 EventArgs 呼叫 OnNewMail。

10.3 設計訂閱者型別

建構函式中 += 訂閱,Unregister 中 -= 取消訂閱。提供回呼方法 FaxMsg(object sender, NewMailEventArgs e)。注意:只能用 +=/-=,不可顯式呼叫 add/remove。事件取消訂閱意義:只要仍有方法訂閱,物件不會被 GC 回收。IDisposable.Dispose 應取消所有事件。

10.2 事件機制(編譯器生成內容)

public event EventHandler<T> NewMail 編譯為:私有委托欄位 NewMail = null;add_NewMail(Delegate.Combine);remove_NewMail(Delegate.Remove)。兩方法標記 [MethodImpl(MethodImplOptions.Synchronized)]。event 為 protected/static/virtual 時,兩方法同樣標記。

10.4 事件與線程安全

  • 實例事件:CLR 使用自身物件作為同步鎖。
  • 靜態事件:CLR 使用型別物件作為同步鎖。
  • 指導方針:方法永勿在物件本身或型別物件上加鎖(鎖對外公開易導致死鎖)。
  • 值類型實例事件:C# 不產生同步屬性,無法保證線程安全;值類型靜態事件則安全。

10.5 顯式控制訂閱/取消訂閱

顯式實作 add/remove 存取器:建立私有委托欄位 m_NewMail 與鎖物件 m_eventLock,在 lock(m_eventLock) 中操作。C# 無法區分編譯器生成與手寫,故仍可用 +=/-=。

10.6 多事件模型

Control 擁有 70+ 事件,若全用上述方式會浪費記憶體。解決方案:註冊工廠 + 事件池(詳見設計模式)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved