none
資源回收前的檔案輸出 RRS feed

  • 問題

  • 各位前輩好

    目前在寫一DLL,會加載在網站專案中

    在站台啟動時,DLL類別中的建構式會去寫出一個檔案訊息,目前測試並無問題

    但在解構時,要進行寫檔卻無法寫出

    我試過幾種方法

    1.解構子

    ~MyClass() { this.WriteLine("Stop") }

    2.Dispose

            public void Dispose()
            {
                this.WriteLine("Stop");

                Dispose(true);
                GC.SuppressFinalize(this);
            }

    or

            private void Dispose(bool _Disposing)
            {
                if (!this.Disposed)
                {
                    if (_Disposing)
                    {
                                this.WriteLine("Stop");
                    }
                }

                this.Disposed = true;
            }

    結果皆無法正確執行

    在VS的Debug Mode中,也無法捕抓到上列各行

    這部份小弟的觀點比較薄弱,還麻煩先進指點一下,感謝

    2010年4月19日 上午 11:26

解答

  • 如果只是要在IIS Stop時記錄一個訊息, 乾脆寫在Global.asax的Application_Stop比較簡單.
    • 已標示為解答 Lolota Lee 2010年4月30日 上午 02:13
    2010年4月20日 上午 02:55
  • 如果你的功能是要將IIS Stop時物件回收問題.但收機制由各物件自行處理回
    以下是我的看法(並未實作)
    1.物件實作IDisposable並做回收機制
    2.網站建立Global.asax並覆寫Application_Stop方法
    3.在Application_Stop方法中呼叫GC.Collect()方法強制回收.

    但如果是靜態變數,以上方是我不確定Application_Stop方法呼叫時是否已作釋放,這部分你可能要測看看.

    • 已標示為解答 Lolota Lee 2010年4月30日 上午 02:13
    2010年4月20日 上午 05:11

所有回覆

  • Hi,

    物件是存放在靜態成員?

    能的話請附上較完整的程式碼

    起碼要有建立物件的程式碼


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/
    2010年4月19日 上午 11:32
  • .Net的資源釋放跟傳統C++不同,C++靠delete由User決定何時釋放.而.Net是透過GC機制由系統來回收,所以正常情況下你無法預知何時GC會啟動作回收機制.
    有很多種作法強制讓GC啟動回收, 但這都不是正確的方式.

    參考一下ado.net的connection物件.他也有實作IDispose介面,但他也產生了另一個公開的Close方法,所以在標準使用ADO.Net的文章都會說明connection使用完需要呼叫close方法.其實即使沒有呼叫,當GC啟動回收時自然也會呼叫Dispose函式,進而間接的呼叫Close方法,但呼叫時機不可預測.

    所以如果你的資源需要即時的處理,你應該提供一個public的方法供使用端決定呼叫時機,並且在Dispose中也呼叫此方法,避免使用端忘記處理.避免資源未釋放問題.

    2010年4月20日 上午 12:29
  • 為方便詢問,將原本較複雜的程式碼精簡如下

    MyLog.dll

    // 靜態類別,便於站台啟用後即可使用,並可擴充其他類型的Log
    public static class MyLog
    {
                 public MyTextLog TextLog = null;
                 public MyLog()
                 {
                              this.TextLog = new MyTextLog();
                 }
    }

    public class MyTextLog : IDisposable
    {
                 private bool            Disposed           = false;
     
                 public MyTextLog()
                 {
                              this.WriteLine("Started");  // OK
                 }

                 ~MyTextLog
                  {
                              this.WriteLine("Stoped");  // 無進行
                  }

                 public void Dispose()
                 {
                              this.WriteLine("Stoped");  // 無進行
                              Dispose(true);
                              GC.SuppressFinalize(this);
                 }

                 private void Dispose(bool _Disposing)
                 {
                              if (!this.Disposed)
                              {
                                           if (_Disposing)
                                           {
                                                        this.WriteLine("Stoped"); // 無進行
                                           }
                              }

                              this.Disposed = true;
                 }

                 public void WriteLine()
                 {
                              // using StreamWriter Output File
                 }
    }

    而原程式有寫公開的Close方法,因避免異常時IO頻繁存取,因此是以delegate的方式來進行,此部份測試均無問題,目前僅在解構時無法正確輸出
    對於GC的機制使用Delegate不定期的進行回收,這我知道,但一直都沒實際去寫過相關的程式,目前一試就覺得自己可能概念不夠清楚
    而上述的語法,是希望在IIS STOP時,會寫輸出一個警示訊息,(是因為IIS STOP後使用Delegate回收,可能要等數分鐘甚至數十分鐘所致嗎?還是想接獲IIS Stop的訊息必須寫在Application_End才行?)
    還請先進指教,謝謝

    2010年4月20日 上午 02:49
  • 如果只是要在IIS Stop時記錄一個訊息, 乾脆寫在Global.asax的Application_Stop比較簡單.
    • 已標示為解答 Lolota Lee 2010年4月30日 上午 02:13
    2010年4月20日 上午 02:55
  • 大大您好,若如此可解決小弟會如此修正

    而在Dispose時,會希望進行另一功能,即檔案Close的動作(擔心其他程式區塊沒處理好,造成回收前檔案沒有關閉的情況,因此在回收前,多買個保險關檔)

    但IIS在Restart時,前一個服務已關閉(目前測試沒測到有執行Dispose裡的程式),而IIS重啟後,此時再重載DLL物件,會去開啟同一份檔案

    如果前一個服務沒有把檔案關閉,此時便會有異常,因目前在測試時,都有做好關檔的動作,所以沒測到這個衝突,但擔心沒處理好,因此想在Dispose買個保險

    故再請教各位前輩們是如何處理這樣的問題呢?

    2010年4月20日 上午 03:06
  • 就是利用IDisposable介面沒錯, 請參考:

    IDisposable: What Your Mother Never Told You About Resource Deallocation

    2010年4月20日 上午 03:18
  • 如果你的功能是要將IIS Stop時物件回收問題.但收機制由各物件自行處理回
    以下是我的看法(並未實作)
    1.物件實作IDisposable並做回收機制
    2.網站建立Global.asax並覆寫Application_Stop方法
    3.在Application_Stop方法中呼叫GC.Collect()方法強制回收.

    但如果是靜態變數,以上方是我不確定Application_Stop方法呼叫時是否已作釋放,這部分你可能要測看看.

    • 已標示為解答 Lolota Lee 2010年4月30日 上午 02:13
    2010年4月20日 上午 05:11