是否有一種簡單的方法遍歷訂閱給定事件的處理程序?我的問題是,客戶訂閱,但忘記取消訂閱,所以發生內存泄漏。我需要一種方法讓對象在Dispose方法中斷開其事件的所有處理程序,這樣就不會發生泄漏 - 至少不是因爲事件。C#如何取消訂閱給定事件的所有事件處理程序?
12
A
回答
11
設置爲null,您的活動:MyEvent = null;
但它確實是更好地使客戶從你的事件退訂。
9
另一種方法是使用所謂的「弱代表」模式。當您使用這種技術時,事件引用客戶端只使用WeakReference
,它不會將它們保留在內存中。當客戶不再從應用程序的其他部分引用時,客戶端將被垃圾回收(並且處理程序也可以在客戶端收集時自動取消註冊)。
這通常用於解決客戶「忘記」退訂.NET事件的問題,所以它聽起來像這可能很適合您的問題。
- 丁丁坎貝爾有一個不錯的article about weak delegates。
- 我也喜歡這個overview at CodeProject,它討論了大部分情景。
- Weak Events也用於WPF,但這種方法似乎有點複雜(對我來說)。
7
只有當另一個對象(偵聽器)死於對象(事件源)之前,內存泄漏纔會發生。在這種情況下,事件源仍然保留對偵聽器的引用,這會阻止收集偵聽器。當事件源死亡時,也可以收集未訂閱的偵聽器。
如果事件源在偵聽器之前死亡,則不會阻止稍後收集偵聽器,此時將其所有其他引用都設置爲空。
這意味着,事件源Dispose方法是不正確的地方解決這個問題。它只能在偵聽器代碼中解決。簡單地說,除了要求你的客戶編寫乾淨的代碼之外,你什麼也做不了。
1
在撰寫本文時,最準確的答案是最不受歡迎的。
你可以使事件處理函數無效,但是在它的所有者被zapped之後無論如何都會被zapped - 它的超級整潔沒有錯,但是像Alex說的那樣,問題不在這裏。
Adi的源代碼類將允許偵聽對象在收集時自動收集,毫無疑問。所以問題在於Adi的源對象保持開放,可能來自客戶代碼中的一長串引用。
以下博客文章還介紹了Adi正在闡述的解決方案,並解釋了爲什麼不必要。
相關問題
- 1. 我必須取消訂閱所有事件處理程序嗎?
- 2. 取消訂閱事件處理程序的策略
- 3. 取消訂閱來自Protected Override Void的事件處理程序
- 4. 事件處理程序未取消訂閱
- 5. 訂閱事件處理程序
- 6. 使用redux-saga處理訂閱/取消訂閱大量事件
- 7. FileSystemWatcher,取消訂閱事件
- 8. 事件取消訂閱
- 9. PropertyChangedEventHandler類型的事件處理程序如何訂閱PropertyChanged事件?
- 10. 如何清除C#中某個特定事件處理程序的訂閱?
- 11. 如何從事件中刪除所有事件處理程序?
- 12. C#.NET合適的事件訂閱和取消訂閱
- 13. 取消onbeforeunload事件處理程序?
- 14. C#事件訂閱
- 15. 如何在greasemonkey中取消綁定jquery事件處理程序?
- 16. C#事件處理程序
- 17. 取消訂閱ViewModels中的EventAggregator事件
- 18. 如何導出所有事件的所有事件訂閱者的計數?
- 19. 如何取消註冊表單事件的所有處理程序?
- 20. 所有端點實例訂閱並處理事件
- 21. C#自定義事件處理程序
- 22. 使用jQuery訂閱DOM事件的多個處理程序
- 23. 的Web應用程序訂閱事件,但不處理它們
- 24. 性能問題 - 取消訂閱事件
- 25. 自動取消訂閱事件
- 26. Angular - 無法從事件取消訂閱()
- 27. Javascript事件處理程序訂單
- 28. 事件處理程序沒有被調用,儘管含訂閱方法C#
- 29. 如何在C#中編寫事件和事件處理程序?
- 30. angular2事件訂閱給未定義
在C#中無法將事件設置爲null。 – 2011-05-25 23:35:50
事實上,如果你是在聲明事件的類內部的話,這是可能的。 – 2011-05-26 03:03:46
你是對的。 – 2011-05-31 17:29:15