是否有一種簡單的方法遍歷訂閱給定事件的處理程序?我的問題是,客戶訂閱,但忘記取消訂閱,所以發生內存泄漏。我需要一種方法讓對象在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. 取消訂閱來自Protected Override Void的事件處理程序
- 3. 取消訂閱事件處理程序的策略
- 4. ReleaseComObject是否等於取消訂閱事件處理程序?
- 5. 事件處理程序未取消訂閱
- 6. 使用GetInvocationList取消訂閱事件處理程序
- 7. 訂閱事件處理程序
- 8. 如何取消訂閱SignalR集線器代理中的事件處理程序?
- 9. 使用redux-saga處理訂閱/取消訂閱大量事件
- 10. 如何在取消訂閱後禁用BackgroundTransferRequest的TransferStatusChanged事件處理程序?
- 11. 事件取消訂閱
- 12. FileSystemWatcher,取消訂閱事件
- 13. C#UI事件取消訂閱 - 必要?
- 14. 如何取消訂閱此.NET事件?
- 15. PropertyChangedEventHandler類型的事件處理程序如何訂閱PropertyChanged事件?
- 16. 如何清除C#中某個特定事件處理程序的訂閱?
- 17. ASP.NET:如何將訂閱的事件處理程序
- 18. 如何從事件中刪除所有事件處理程序?
- 19. 取消訂閱事件處理程序C#,使用默認處理程序代替
- 20. C#.NET合適的事件訂閱和取消訂閱
- 21. C#事件和事件處理程序
- 22. 取消onbeforeunload事件處理程序?
- 23. C#事件訂閱
- 24. C#訂閱事件
- 25. C#事件訂閱和取消訂閱重複項
- 26. 如何在greasemonkey中取消綁定jquery事件處理程序?
- 27. C#事件處理程序
- 28. 取消訂閱ViewModels中的EventAggregator事件
- 29. 如何同時調用所有事件處理程序綁定到事件
- 30. 何時取消訂閱自定義控件中的事件
在C#中無法將事件設置爲null。 – 2011-05-25 23:35:50
事實上,如果你是在聲明事件的類內部的話,這是可能的。 – 2011-05-26 03:03:46
你是對的。 – 2011-05-31 17:29:15