[c#] 為什麼這不會導致事件未訂閱時內存洩漏


0 Answers

答案實際上是在你已經鏈接到的問題的答案中:

當偵聽器將事件偵聽器附加到事件時,源對象將獲得對偵聽器對象的引用。 這意味著監聽器不能被垃圾收集器收集,直到事件處理程序被分離,或者收集源對象

你正在釋放對象( Person ),這樣Listener (你的Form )就可以被收集,這就是為什麼沒有內存洩漏的原因。

內存洩漏將發生,當這種情況是圍繞IE的另一種方式,當你想處置的Form但事件 (你的Person對象)仍然活著持有一個引用。

Question

我想了解事件如何導致內存洩漏。 我在這個 問題找到了一個很好的解釋,但是當在Windg中查看對象時,我對結果感到困惑。 首先,我有一個簡單的類如下。

class Person
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }

        public event EventHandler UponWakingUp;
        public Person()  {  }

        public void Wakeup()
        {
            Console.WriteLine("Waking up");
            if (UponWakingUp != null)
                UponWakingUp(null, EventArgs.Empty);
        }
    }

現在我在Windows窗體應用程序中使用這個類,如下所示。

public partial class Form1 : Form
    {
        Person John = new Person() { LastName = "Doe", FirstName = "John" };

        public Form1()
        {
            InitializeComponent();

            John.UponWakingUp += new EventHandler(John_UponWakingUp);
        }

        void John_UponWakingUp(object sender, EventArgs e)
        {
            Console.WriteLine("John is waking up");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            John = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            MessageBox.Show("done");
         }
    }

正如你所看到的,我instaniated人類和訂閱UponWakingUp事件。 我在這個表單上有一個按鈕。 當用戶點擊這個按鈕時,我將這個Person實例設置為null,而不用取消訂閱事件。 然後我打電話給GC.Collect以確保Garbade收集已經完成。 我在這裡顯示一個消息框,以便我可以附加Windbg來查看引用幫助的Form1類和在這個類內我沒有看到任何引用該事件(Windbg輸出如下所示,雖然Form1有太長的數據,我顯示與我的問題有關)。 這個類有一個Person類的引用,但是它是空的。 基本上,這似乎不是一個內存洩漏給我,因為Form1沒有任何引用人類,即使你沒有退訂。

我的問題是,如果這確實造成內存洩漏。 如果沒有,為什麼不呢?

0:005> !do 0158d334   
Name:        WindowsFormsApplication1.Form1  
MethodTable: 00366390  
EEClass:     00361718  
Size:        332(0x14c) bytes  
File:        c:\Sandbox\\WindowsFormsApplication1\WindowsFormsApplication1\bin\Debug\WindowsFormsApplication1.exe  
Fields:  
      MT    Field   Offset                 Type VT     Attr    Value Name  
619af744  40001e0        4        System.Object  0 instance 00000000 __identity  
60fc6c58  40002c3        8 ...ponentModel.ISite  0 instance 00000000 site  
619af744  4001534      b80        System.Object  0   static 0158dad0 EVENT_MAXIMIZEDBOUNDSCHANGED  
**00366b70  4000001      13c ...plication1.Person  0 instance 00000000 John**  
60fc6c10  4000002      140 ...tModel.IContainer  0 instance 00000000 components  
6039aadc  4000003      144 ...dows.Forms.Button  0 instance 015ad06c button1  

0:008> !DumpHeap -mt 00366b70    
 Address       MT     Size  
total 0 objects  
Statistics:  
      MT    Count    TotalSize Class Name  
Total 0 objects  



Related