2013年4月3日 星期三

資源回收方法與基礎

前篇 理解記憶體配置之後 可以開始記錄如何有效管理記憶體的配置

建立類別 與 解構

先建立類別 利用~來解構類別 並SHOW出訊息告知已解構
class Father
        {
            public Father()
            {
                MessageBox.Show("類別狀態:建構 Father");
            }
            ~Father()
            {
                MessageBox.Show("類別狀態:解構 Father");
            }
        }
       
        class Son : Father
        {
            public Son()
            {
                MessageBox.Show("類別狀態:建構 Son");
            }
            ~Son()
            {
                MessageBox.Show("類別狀態:解構 Son");
            }
        }




再來 來試試看 執行的步驟 建立BUTTON
private void button1_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "程式開始" + "\n"; ;
            Son me = new Son();
            me = null;
            richTextBox1.Text += "程式結束" + "\n";
            //直到程式被關閉 才會執行解構
        }



執行 先後順序 如下
程式開始
建構FATER
建構SON
程式結束
會發現程式 尚未解構 
直到把程式關閉 才SHOW出 解構訊息
因為使用~來解構 會呼叫Object.Finalize方法
而Finalize只是 允許物件在記憶體回收進行回收之前,嘗試釋放資源並執行其他清除作業。

下面列子中 與上一樣 不同與加入 GC強迫回收!
PS:使用 同上一樣的類別
private void button2_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "程式開始" + "\n";
            Son me = new Son();
            me = null;
            richTextBox1.Text += "開始執行強迫回收"+"\n";
            //以GC指令強迫.Net framework資源回收
            GC.Collect();
            //並使用WaitForPendingFinalizers method等到確實回收後
            //再繼續執行,因為資源回收時是在另一個thread之故。
            GC.WaitForPendingFinalizers();
            richTextBox1.Text += "程式結束" + "\n";
        }

執行順序為
程式開始
建構FATER
建構SON
解構SON
解構FATER
程式結束

可以程式尚未結束 先進行回收




再來可以使用IDisposable介面
類別程式碼如下
class FFather : IDisposable //父類別直接指向IDisposable
        {
            public FFather()
            {
                MessageBox.Show("類別狀態:建構 FFather");
            }
            public void Dispose()
            {
                MessageBox.Show("類別狀態:解構 FFather");
            }
        }
        class SSon : FFather, IDisposable
        {
            public SSon()
            {
                MessageBox.Show("類別狀態建構 SSon");
            }
            new public void Dispose()
            {
                MessageBox.Show("類別狀態解構 SSon");
            }
        }




一樣寫個BUTTON來看執行順序

private void button3_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = ("程式開始");
            using (SSon me = new SSon())
            {
                richTextBox1.Text += ("程式執行中");
            }
            richTextBox1.Text += ("程式結束");
            //只有呼叫子類別的回收
        }



執行順序如下
程式開始
建構FFATHER
建構SSON
解構SSON
程式結束

PS:一定會覺得奇怪 FFATHER怎沒被解構?

Net framework只呼叫子類別的Dispose method 卻沒有呼叫父類別的Dispose method,所以,實作IDisposable介面時,父類別的資源回收要由子類別呼叫

請看下面 類別改寫 加入base.Dispose()


class FFFather : IDisposable //父類別直接指向IDisposable
        {
            public FFFather()
            {
                MessageBox.Show("類別狀態:建構 FFFather");
            }
            public void Dispose()
            {
                MessageBox.Show("類別狀態:解構 FFFather");
            }
        }
        class SSSon : FFFather, IDisposable
        {
            public SSSon()
            {
                MessageBox.Show("類別狀態建構 SSSon");
            }
            new public void Dispose()
            {
                MessageBox.Show("類別狀態解構 SSSon");
                base.Dispose();
            }
        }


執行順序如下
程式開始
建構FFFATHER
建構SSSON
解構SSSON
解構FFFATHER
程式結束


注意使用  IDisposable介面時候
建立物件時 務必使用 using
如果不使用using IDisposable將毫無作用


沒有留言:

張貼留言