2023年8月9日 星期三

[C#] 沒有取消訂閱(unsubscribe)事件(Event)會導致memory leak?

 Publisher物件可提供事件供其他subscriber物件做訂閱,且一般也會在適當的時機點取消訂閱,

但如果只訂閱但沒有取消訂閱,會讓程式memory leak嗎?


我將情境分為以下4種:

1. Publisher生命週期較subscriber長,subscriber有取消訂閱。

2. Publisher生命週期較subscriber長,subscriber沒有取消訂閱。

3. Publisher生命週期較subscriber短,subscriber有取消訂閱。

4. Publisher生命週期較subscriber短,subscriber沒有取消訂閱。


Publisher使用下圖的Server類別:

Subscriber使用下圖的Log類別,Log訂閱Server的ServerConnected事件:


以下依序列出測試結果,這裡使用VS內建的記憶體快照來確認物件是否已GC:

1. Publisher生命週期較subscriber長,subscriber有取消訂閱:

    可以看到Log物件(subscriber)已經被GC了。

2. Publisher生命週期較subscriber長,subscriber沒有取消訂閱:

    可以看到Log物件(subscriber)還存在記憶體。

3. Publisher生命週期較subscriber短,subscriber有取消訂閱:

4. Publisher生命週期較subscriber短,subscriber沒有取消訂閱:

情境3跟4,都是Server物件先回收,Log物件還留著的情形,記憶體快照也是一樣結果,
代表publisher先回收的話,subscriber沒有取消事件訂閱,也沒有關係:


結論是,subscriber還是要在適當時機點取消事件訂閱,如同情境2的結果,訂閱長生命週期的事件,是會造成memory leak的。