铁血规则:事件预订与取消预订[转]
鐵血規則:事件預訂與取消預訂
在編碼的時候,我們經常預訂某個事件來處理它,但很少取消事件的預訂,這種做法可能導致程序在運行時出現一些異常。
????? 如果你的某個用于處理事件的對象不是在運行期內永久存在的(比如,不是Singleton對象),那么請記住一條規則:在該對象(事件預訂者)的生命周期中只要預訂了其他對象(事件發布者)的事件,那么在該對象釋放時,一定要取消這些事件的預訂。否則,在預訂者被釋放后,發布者仍然保持著預訂者的引用,在對應的事件被觸發時,發布者仍然會持有預訂者的引用(導致內存泄露),并且調用預訂者的處理函數,而由于預訂者已經被釋放,所以可能引發莫名其妙的問題。(這條規則很早就總結出來了,最近卻忘記了,以至于浪費了半天的時間來跟蹤一個奇怪的現象。以此記錄作為前車之鑒,呵呵)
????? 實踐這條規則很簡單,一般這樣做就可以了:
(1)在預訂者的構造函數或初始化函數中預訂事件。
(2)在預訂者的析構函數或Dispose方法中取消事件預訂。
????? 比如:
publicclassPublisher????{
????????publiceventCbGeneric?SomeEvent;
????}
????publicclassSubscriber?:IDisposable
????{
????????privatePublisher?publisher;
????????publicSubscriber(Publisher?_publisher)
????????{
????????????this.publisher?=_publisher?;
????????????//預訂事件
this.publisher.SomeEvent?+=newCbGeneric(publisher_SomeEvent);
????????}
????????voidpublisher_SomeEvent()
????????{
????????????//處理事件
}
????????publicvoidDispose()
????????{
????????????//取消預訂
this.publisher.SomeEvent?-=newCbGeneric(publisher_SomeEvent);
????????}
????} 復制代碼
??????特別是當預訂者是自定義的windows控件時(從Control類繼承),我們可以在其自身的Disposed事件中,來取消對發布者的事件預訂。當包含該控件對象的宿主Form被關閉時,控件對象也會被釋放,這可能是一個很隱蔽的問題,以至于我們忘了在控件被釋放時取消必須的事件預訂。
????? 我們也許想到,如果發布者與預訂者的生命周期是完全相同的,是不是就不需要取消預訂了?大多數情況下是可以的,但是你要保證你的發布者對象在被釋放后,是否還被其他的對象持有引用,這樣也可能會導致內存泄露以及其他問題。所以,我們建議,既然預訂了事件,就請在預訂者被釋放時,取消這些預訂。
?
?
轉載于:https://www.cnblogs.com/08shiyan/archive/2012/03/08/2385296.html
總結
以上是生活随笔為你收集整理的铁血规则:事件预订与取消预订[转]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mac OS 错误代码 -8072的可行
- 下一篇: 【Linux学习记录】Linux磁盘与文