WeakEventManager弱事件模式
在應用程式中,為了與將處理程式附加到事件源的偵聽器物件配合,附加到該事件源的處理程式可能不會被破壞。這種情況可能會導致記憶體洩漏。 Windows Presentation Foundation (WPF) 引入了可用於解決此問題的設計模式,該模式為特定事件提供專用管理器類併為該事件的偵聽器實現介面。 此設計模式稱為“弱事件模式”。
偵聽事件可能會導致記憶體洩漏。 偵聽事件的一般方法是使用語言特定的語法,該語法將處理程式附加到源上的事件。 例如,在 C# 中,該語法是:source.SomeEvent += new SomeEventHandler(MyEventHandler)。
此方法建立從事件源到事件偵聽器的強引用。 通常,為偵聽器附加事件處理程式會導致偵聽器具有物件生存期,該生存期受源的物件生存期影響(除非顯式移除了事件處理程式)。 但在某些情況下,您可能希望偵聽器的物件生存期受其他因素(例如物件生存期當前是否屬於應用程式的視覺化樹)控制,而不受源的生存期控制。 如果源物件生存期超出了偵聽器的物件生存期,則常規事件模式會導致記憶體洩漏:偵聽器保持活動狀態的時間比預期要長。
弱事件模式旨在解決此記憶體洩漏問題。 每當偵聽器需要註冊事件,而該偵聽器並不明確瞭解什麼時候登出時,就可以使用弱事件模式。 當源的物件生存期超出偵聽器的有用物件生存期時,也可以使用弱事件模式。 (在這種情況下,有用由您確定。)使用弱事件模式,偵聽器可以註冊和接收事件,同時不會對偵聽器的物件生存期特徵產生任何影響。 實際上,來自源的隱含引用無法確定偵聽器是否適合進行垃圾回收。 該引用為弱引用,僅是弱事件模式和相關 API 的命名。 可以對偵聽器進行垃圾回收或銷燬,在不保留對現在銷燬的物件的非可收集處理程式引用的情況下,源可以繼續。
實現弱事件模式主要是對於控制元件作者而言是很有趣味的。 這是因為控制元件作者主要負責控制元件的行為和包容以及控制元件對其所插入到的應用程式的影響。 這包括控制元件物件生存期行為,特別是對所描述的記憶體洩漏問題的處理。
某些方案本質上適合應用弱事件模式。 資料繫結就是這樣一個方案。 在資料繫結中,通常源物件完全獨立於偵聽器物件,而該偵聽器物件是繫結的目標。WPF 資料繫結的許多方面在實現事件的方式上已應用了弱事件模式。
可通過三種方式實現弱事件模式。 ,當您應使用每一時,下表列出了三種方法並提供某些指南。
1使用現有弱事件管理器類
如果希望訂閱的事件具有相應的 WeakEventManager,使用現有的弱事件管理器。 有關所附帶的 WPF 弱事件管理器的列表,請參見。WeakEventManager 類的繼承層次結構。 但是,請注意,具有相對包含 WPF 的較弱事件管理器,因此,您可能需要選擇其他方法之一。
2使用泛型弱事件管理器類
使用泛型 WeakEventManager<TEventSource, TEventArgs> ,當現有 WeakEventManager 不可用時,您需要一種簡單的方法實現,因此,您不考慮效能。 泛型 WeakEventManager<TEventSource, TEventArgs> 比現有或自定義弱事件管理器效率低。 例如,泛型類執行更多反射發現命名該事件的名稱。 此外,註冊的程式碼使用常規 WeakEventManager<TEventSource, TEventArgs> 事件使用現有或自定義 WeakEventManager詳細的速度。
3建立自定義弱事件管理器類
建立自定義 WeakEventManager ,在現有 WeakEventManager 不可用時,並且您希望在最好的效能。 使用自定義 WeakEventManager 訂閱事件將更為有效的,但是,則會先編寫更多程式碼的成本。
以下各節描述如何實現弱事件模式。 在本討論中的目的,訂閱的事件具有下列特徵。
-
操作名稱為 SomeEvent。
-
事件由 EventSource 類引發。
-
事件處理程式具有型別: SomeEventEventHandler (或 EventHandler<SomeEventEventArgs>)。
-
事件通過型別 SomeEventEventArgs 的引數為事件處理程式。
使用現有弱事件管理器類
-
查詢現有弱事件管理器。
有關所附帶的 WPF 弱事件管理器的列表,請參見。 WeakEventManager 類的繼承層次結構。
-
使用新的弱事件管理器而不是常規事件掛接。
例如,因此,如果程式碼使用以下模式訂閱事件:
source.SomeEvent += new SomeEventEventHandler(OnSomeEvent);
將其更改為以下模式:
SomeEventWeakEventManager.AddHandler(source, OnSomeEvent);
同樣,因此,如果程式碼使用以下模式取消訂閱事件:
source.SomeEvent -= new SomeEventEventHandler(OnSome);
將其更改為以下模式:
SomeEventWeakEventManager.RemoveHandler(source, OnSomeEvent);
使用泛型弱事件管理器類
-
使用泛型 WeakEventManager<TEventSource, TEventArgs> 類而不是常規事件掛接。
當您使用 WeakEventManager<TEventSource, TEventArgs> 註冊事件偵聽器時,如下面的程式碼所示,可以提供事件源和 EventArgs 型別為型別引數提供類並呼叫 AddHandler :
WeakEventManager<EventSource, SomeEventEventArgs>.AddHandler(source, "SomeEvent", source_SomeEvent);
建立自定義弱事件管理器類
-
複製下面的類别範本新增到專案。
此類從 WeakEventManager 類繼承。
class SomeEventWeakEventManager : WeakEventManager { private SomeEventWeakEventManager() { } /// <summary> /// Add a handler for the given source's event. /// </summary> public static void AddHandler(EventSource source, EventHandler<SomeEventEventArgs> handler) { if (source == null) throw new ArgumentNullException("source"); if (handler == null) throw new ArgumentNullException("handler"); CurrentManager.ProtectedAddHandler(source, handler); } /// <summary> /// Remove a handler for the given source's event. /// </summary> public static void RemoveHandler(EventSource source, EventHandler<SomeEventEventArgs> handler) { if (source == null) throw new ArgumentNullException("source"); if (handler == null) throw new ArgumentNullException("handler"); CurrentManager.ProtectedRemoveHandler(source, handler); } /// <summary> /// Get the event manager for the current thread. /// </summary> private static SomeEventWeakEventManager CurrentManager { get { Type managerType = typeof(SomeEventWeakEventManager); SomeEventWeakEventManager manager = (SomeEventWeakEventManager)GetCurrentManager(managerType); // at first use, create and register a new manager if (manager == null) { manager = new SomeEventWeakEventManager(); SetCurrentManager(managerType, manager); } return manager; } } /// <summary> /// Return a new list to hold listeners to the event. /// </summary> protected override ListenerList NewListenerList() { return new ListenerList<SomeEventEventArgs>(); } /// <summary> /// Listen to the given source for the event. /// </summary> protected override void StartListening(object source) { EventSource typedSource = (EventSource)source; typedSource.SomeEvent += new EventHandler<SomeEventEventArgs>(OnSomeEvent); } /// <summary> /// Stop listening to the given source for the event. /// </summary> protected override void StopListening(object source) { EventSource typedSource = (EventSource)source; typedSource.SomeEvent -= new EventHandler<SomeEventEventArgs>(OnSomeEvent); } /// <summary> /// Event handler for the SomeEvent event. /// </summary> void OnSomeEvent(object sender, SomeEventEventArgs e) { DeliverEvent(sender, e); } }
-
將替換 SomeEventWeakEventManager 名稱擁有名稱。
-
用相應的名稱替換前面所述的三個名稱事件。 (SomeEvent、 EventSource和 SomeEventEventArgs)
-
設定可見性 (公共/內部/私有) 弱事件管理器類將與事件它管理的可見性。
-
使用新的弱事件管理器而不是常規事件掛接。
例如,因此,如果程式碼使用以下模式訂閱事件:
source.SomeEvent += new SomeEventEventHandler(OnSomeEvent);
將其更改為以下模式:
SomeEventWeakEventManager.AddHandler(source, OnSomeEvent);
同樣,因此,如果程式碼使用以下模式取消訂閱事件:
source.SomeEvent -= new SomeEventEventHandler(OnSome);
將其更改為以下模式:
SomeEventWeakEventManager.RemoveHandler(source, OnSomeEvent);
相關文章
- 在設計模式中是怎樣達到弱耦合的?設計模式
- 事件驅動及其設計模式事件設計模式
- JS觀察者模式-自定義事件JS模式事件
- Event-Listerner事件監聽模式事件模式
- mvvm模式 事件觸發器[wpf]MVVM模式事件觸發器
- 動態賦值弱型別值物件--Dynamic Create Value Object 模式 (轉)賦值型別物件Object模式
- 求助:關於“JAVA事件處理模式”Java事件模式
- php弱型別PHP型別
- 弱口令weblogicWeb
- 弱網測試
- 弱口令測試
- SSL/TLS協議安全系列:CBC 模式的弱安全性介紹(一)TLS協議模式
- 事件溯源:投影或投射模式 -Kacper Gunia事件模式
- 事件匯流排EventBus和觀察者模式事件模式
- 事件溯源與流水賬的結賬模式事件模式
- 談談.NET中常見的記憶體洩露問題——GC、委託事件和弱引用記憶體洩露GC事件
- Java中的弱引用Java
- rm命令弱爆了!
- Java弱引用與WeakHashMapJavaHashMap
- 設計模式之釋出訂閱模式(4) Guava Eventbus 事件處理設計模式Guava事件
- 拯救祭天的程式設計師——事件溯源模式程式設計師事件模式
- 事理圖譜:事件演化的規律和模式事件模式
- 首頁 Java事件處理模式 最後完稿。Java事件模式
- 幹掉Switch-Case、If-Else----訂閱釋出模式+事件驅動模式模式事件
- Swift 4 弱引用實現Swift
- msvc很多地方比gcc弱GC
- Python 弱引用 學習Python
- 理解Java中的弱引用Java
- 事件溯源模式:分離事件的發生和捕獲兩種不同時間 - verraes事件模式
- 設計模式(六)觀察者模式詳解(包含觀察者模式JDK的漏洞以及事件驅動模型)設計模式JDK事件模型
- 菜鳥弱弱地問:找個薪資待遇差的工作能成長嗎?
- javascript設計模式(張容銘)學習筆記 – 外觀模式繫結事件JavaScript設計模式筆記事件
- SpringBoot事件監聽機制及觀察者模式/釋出訂閱模式Spring Boot事件模式
- Linux(伺服器程式設計):15---兩種高效的事件處理模式(reactor模式、proactor模式)Linux伺服器程式設計事件模式React
- 弱弱的問一個菜鳥問題(關於單態和連線池)
- 設計模式之釋出訂閱模式(3) 深入Spring Events事件驅動模型設計模式Spring事件模型
- QNET 弱網測試工具
- 淺談PHP弱型別安全PHP型別