铁血规则:事件预订与取消预订
在編碼的時(shí)候,我們經(jīng)常預(yù)訂某個(gè)事件來處理它,但很少取消事件的預(yù)訂,這種做法可能導(dǎo)致程序在運(yùn)行時(shí)出現(xiàn)一些異常。
????? 如果你的某個(gè)用于處理事件的對(duì)象不是在運(yùn)行期內(nèi)永久存在的(比如,不是Singleton對(duì)象),那么請(qǐng)記住一條規(guī)則:在該對(duì)象(事件預(yù)訂者)的生命周期中只要預(yù)訂了其他對(duì)象(事件發(fā)布者)的事件,那么在該對(duì)象釋放時(shí),一定要取消這些事件的預(yù)訂。否則,在預(yù)訂者被釋放后,發(fā)布者仍然保持著預(yù)訂者的引用,在對(duì)應(yīng)的事件被觸發(fā)時(shí),發(fā)布者仍然會(huì)持有預(yù)訂者的引用(導(dǎo)致內(nèi)存泄露),并且調(diào)用預(yù)訂者的處理函數(shù),而由于預(yù)訂者已經(jīng)被釋放,所以可能引發(fā)莫名其妙的問題。(這條規(guī)則很早就總結(jié)出來了,最近卻忘記了,以至于浪費(fèi)了半天的時(shí)間來跟蹤一個(gè)奇怪的現(xiàn)象。以此記錄作為前車之鑒,呵呵)
????? 實(shí)踐這條規(guī)則很簡單,一般這樣做就可以了:
(1)在預(yù)訂者的構(gòu)造函數(shù)或初始化函數(shù)中預(yù)訂事件。
(2)在預(yù)訂者的析構(gòu)函數(shù)或Dispose方法中取消事件預(yù)訂。
????? 比如:
??? public?class?Publisher????{
????????public?event?CbGeneric?SomeEvent;
????}
????public?class?Subscriber?:IDisposable
????{
????????private?Publisher?publisher;
????????public?Subscriber(Publisher?_publisher)
????????{
????????????this.publisher?=?_publisher?;
????????????//預(yù)訂事件
????????????this.publisher.SomeEvent?+=?new?CbGeneric(publisher_SomeEvent);
????????}
????????void?publisher_SomeEvent()
????????{
????????????//處理事件
????????}
????????public?void?Dispose()
????????{
????????????//取消預(yù)訂
????????????this.publisher.SomeEvent?-=?new?CbGeneric(publisher_SomeEvent);
????????}
????}
??????特別是當(dāng)預(yù)訂者是自定義的windows控件時(shí)(從Control類繼承),我們可以在其自身的Disposed事件中,來取消對(duì)發(fā)布者的事件預(yù)訂。當(dāng)包含該控件對(duì)象的宿主Form被關(guān)閉時(shí),控件對(duì)象也會(huì)被釋放,這可能是一個(gè)很隱蔽的問題,以至于我們忘了在控件被釋放時(shí)取消必須的事件預(yù)訂。
????? 我們也許想到,如果發(fā)布者與預(yù)訂者的生命周期是完全相同的,是不是就不需要取消預(yù)訂了?大多數(shù)情況下是可以的,但是你要保證你的發(fā)布者對(duì)象在被釋放后,是否還被其他的對(duì)象持有引用,這樣也可能會(huì)導(dǎo)致內(nèi)存泄露以及其他問題。所以,我們建議,既然預(yù)訂了事件,就請(qǐng)?jiān)陬A(yù)訂者被釋放時(shí),取消這些預(yù)訂。
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhuweisky/archive/2011/04/07/2008145.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的铁血规则:事件预订与取消预订的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客小白月赛12 H华华和月月种树 (
- 下一篇: MOSS服务器场迁移1-有关切换登录用户