最近敝人在WinCE-based上開發的模組越來越龐大,另一方面是IO處理頻繁,執行一兩天就會因資源不足導致Shutdown。沒錯,資源對於WinCE而言一直都是相當棘手的問題,畢竟WinCE的記憶體和虛擬記憶體空間都不像桌上型電腦龐大,可以想怎麼用就怎麼用。因此,當我們針對WinCE模組設計時,除了程式資源分配盡量優化外,更重要的是需考慮其模組資源上的使用與釋放,如此的系統才能經的起長時間的考驗。以下是網路一篇文章,我覺得很淺顯易懂,在此就暫時引用一下這位高手的文獻,供大家參考:

 

(作者:史帝芬)


    .Net framework和Java VM一樣針對一般資源會自動回收,對於
unmanaged的資源,Java會於finalize
做處理,語法上C#和C++相同,作法上則和Java相同,都是交給VM處理。
事實上,C#也有個Finalize method,這個method與Java的finalize相同,於物件將被回收時會被
VM呼叫。C#的編譯器在編譯時實際上會將解構子轉換成Finalize的覆載method,如下所示。


class MyClass
{
~MyClass() { ... }
}
會轉換成:
class MyClass
{
protected override void Finalize()
{
try { ... }
finally { base.Finalize(); }
}
}



  • 解構子


        C#提供了與C++一樣語法的解構子,當object消失時,.Net framework
    會執行解構子,我們可於此時加入程式進行資源回收,與Java相同的是,什麼時候object會消失?
    這由VM決定,並非在object變成null時,VM即會立刻執行解構子並回收object。底下範例程式1.1可以看出,.Net framework
    會先建構父類別再建構子類別,解構時則會以反方向,先解構子類別,再解構父類別,特別注意的
    是,解構子不需由程式呼叫,.Net framework會自動執行。

        如果要強迫.Net framework資源回收,可以使用如範例程式1.2的方法,
    以GC指令強迫.Net framework資源回收,並使用WaitForPendingFinalizers method等到確實回收後
    再繼續執行,因為資源回收時是在另一個thread之故。



    * 範例程式 1.1


    using System;

    namespace Garbage
    {
    class Father
    {
    public Father()
    {
    Console.WriteLine("建構 Father");
    }

    ~Father()
    {
    Console.WriteLine("解構 Father");
    }
    }

    class Son : Father
    {
    public Son()
    {
    Console.WriteLine("建構 Son");
    }

    ~Son()
    {
    Console.WriteLine("解構 Son");
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("程式開始");
    Son me = new Son();
    me = null;
    Console.WriteLine("程式結束");
    }
    }
    }

    * 執行結果 1.1


    程式開始
    建構 Father
    建構 Son
    程式結束
    解構 Son
    解構 Father




    * 範例程式 1.2


    using System;

    namespace Garbage
    {
    class Father
    {
    public Father()
    {
    Console.WriteLine("建構 Father");
    }

    ~Father()
    {
    Console.WriteLine("解構 Father");
    }
    }

    class Son : Father
    {
    public Son()
    {
    Console.WriteLine("建構 Son");
    }

    ~Son()
    {
    Console.WriteLine("解構 Son");
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("程式開始");
    Son me = new Son();
    me = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
    Console.WriteLine("程式結束");
    }
    }
    }

    * 執行結果 1.2


    程式開始
    建構 Father
    建構 Son
    解構 Son
    解構 Father
    程式結束



  • 實作IDisposable介面

        IDisposable介面僅有一個method -- Dispose,實作IDisposable
    介面後,在using中.Net framework將會自動呼叫Dispose method回收資源,如範例程式 2.1
    所示。但是由執行結果2.1各位是否看出端倪? .Net framework只呼叫子類別的Dispose method
    卻沒有呼叫父類別的Dispose method,所以,實作IDisposable介面時,父類別的資源回收要
    由子類別呼叫,請看範例程式2.2。


        範例程式 2.3是讓各位了解,實作IDisposable介面在using中.Net
    framework會自動呼叫Dispose method進行資源回收,但是在一般狀況下並不會。需要程式自行
    呼叫Dispose method或是改成如範例程式 2.4所示,其中GC.SuppressFinalize(this)是通知
    .Net framework不要再對這個object進行資源回收,如果不這麼做,當主程式中自行呼叫Dispose method,
    .Net framework又於object消失後執行解構子,會造成Dispose method重複執行。



    * 範例程式 2.1


    using System;

    namespace Garbage2
    {
    class Father : IDisposable
    {
    public Father()
    {
    Console.WriteLine("建構 Father");
    }

    public void Dispose()
    {
    Console.WriteLine("解構 Father");
    }
    }

    class Son : Father, IDisposable
    {
    public Son()
    {
    Console.WriteLine("建構 Son");
    }

    new public void Dispose()
    {
    Console.WriteLine("解構 Son");
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("程式開始");
    using (Son me = new Son())
    {
    Console.WriteLine("程式執行中");
    }
    Console.WriteLine("程式結束");
    }
    }
    }

    * 執行結果 2.1


    程式開始
    建構 Father
    建構 Son
    程式執行中
    解構 Son
    程式結束

    * 範例程式 2.2


    using System;

    namespace Garbage2
    {
    class Father : IDisposable
    {
    public Father()
    {
    Console.WriteLine("建構 Father");
    }

    public void Dispose()
    {
    Console.WriteLine("解構 Father");
    }
    }

    class Son : Father, IDisposable
    {
    public Son()
    {
    Console.WriteLine("建構 Son");
    }

    new public void Dispose()
    {
    Console.WriteLine("解構 Son");
    base.Dispose();
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("程式開始");
    using (Son me = new Son())
    {
    Console.WriteLine("程式執行中");
    }
    Console.WriteLine("程式結束");
    }
    }
    }

    * 執行結果 2.2


    程式開始
    建構 Father
    建構 Son
    程式執行中
    解構 Son
    解構 Father
    程式結束


    * 範例程式 2.3 (僅有主程式,其餘請參考2.2)


    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("程式開始");
    Son me = new Son();
    me = null;
    Console.WriteLine("程式結束");
    }
    }

    * 執行結果 2.3



    程式開始
    建構 Father
    建構 Son
    程式結束


    * 範例程式 2.4


    using System;

    namespace Garbage2
    {
    class Father : IDisposable
    {
    public Father()
    {
    Console.WriteLine("建構 Father");
    }

    public void Dispose()
    {
    Console.WriteLine("解構 Father");
    GC.SuppressFinalize(this);
    }

    ~Father()
    {
    Dispose();
    }
    }

    class Son : Father, IDisposable
    {
    public Son()
    {
    Console.WriteLine("建構 Son");
    }

    new public void Dispose()
    {
    Console.WriteLine("解構 Son");
    GC.SuppressFinalize(this);
    }

    ~Son()
    {
    Dispose();
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("程式開始");
    Son me = new Son();
    me = null;
    Console.WriteLine("程式結束");
    }
    }
    }

    * 執行結果 2.4


    程式開始
    建構 Father
    建構 Son
    程式結束
    解構 Son
    解構 Father




  • 創作者介紹

    傑克鼠的下午茶

    傑克鼠 發表在 痞客邦 PIXNET 留言(0) 人氣()