2011-07-06 2 views
2

C#でCOM Excel Applicationクラスを使用しています。私はWorkbookBeforeCloseを扱った。しかし、今私はCOMオブジェクトを適切に解放することはできません。.NETでイベントを処理するときにすべてのCOMオブジェクトを解放する方法

このイベントを処理する前にCOMオブジェクトを適切にリリースすることができましたが、そのコードの部分にコメントするときは、アプリケーションが正常に動作することに注意してください。

メモリから解放されたCOMオブジェクトとその解放方法を教えてください。

編集:

public void Init() 
{ 
    ... 
    application = new Excel.Application(); 
    application.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(application_WorkbookBeforeClose); 
} 
... 
void application_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel) 
    { 
     if (WorkbookBeforeClose != null) 
     { 
      ExcelCloseEventArgs args = new ExcelCloseEventArgs(); 
      WorkbookBeforeClose(this, args); 
      Cancel = args.Cancel; 
     } 
     else 
      Cancel = false; 
    } 
... 
private void closeExcel() 
    { 
     try 
     { 
      if (workbook != null) 
      { 
       workbook.Close(false); 
      } 
     } 
     catch (Exception e) { } 
     finally 
     { 
      if (workbooks != null) 
       Marshal.ReleaseComObject(workbooks); 
      if (workbook != null) 
       Marshal.ReleaseComObject(workbook); 
     } 

     try 
     { 
      if (application != null) 
      { 
       application.WorkbookBeforeClose -= handler; 
       application.Quit(); 
       Marshal.ReleaseComObject(application); 
       Marshal.ReleaseComObject(handler); 
       process.WaitForExit(); 
      } 
     } 
     catch (Exception e) { throw; } 
     finally 
     { 

     } 

     workbook = null; 
     workbooks = null; 
     application = null; 
     if (process != null && !process.HasExited) 
      process.Kill(); 
     if (threadCulture != null) 
      Thread.CurrentThread.CurrentCulture = threadCulture; 
     initialized = false; 
    } 

アプリケーションが行process.WaitForExit()で一時停止:私はやった

+0

あなたが行ったことを私たちに見せてもらえますか?何が間違っているのを見ることができますか? –

答えて

3

メモリ管理は.NETでは自動的に行われます。 Marshal.ReleaseComObject()を明示的に呼び出すのは間違いです。あまりにも早い時期にRCWを簡単にクラッシュさせることができるだけでなく、特に参照カウントがしばしば隠されるためです。インデクサーやイベントは難しいものです。 1つの欠落したReleaseComObject呼び出しは、それを世話するガベージコレクタにフォールバックするのに十分です。 GCがメモリー(および参照カウント)を解放するまでに時間がかかることは、バグではなく機能です。

ガベージコレクタに世話をする代わりに、COMサーバーをオンデマンドで終了させたい場合は、すべての参照をnullに設定し、イベントハンドラの登録を解除してGC.Collect()を呼び出します。 ReleaseComObject呼び出しは必要ありません。プロによる洞察については、this blog postをチェックしてください。

0

私はcloseExcel方法でこれらのコード行を変更することによって、自分のコードを修正:

if (application != null) 
{ 
    application.WorkbookBeforeClose -= new Excel.AppEvents_WorkbookBeforeCloseEventHandler(application_WorkbookBeforeClose); 
    application.Quit(); 
    Marshal.ReleaseComObject(application); 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
    process.WaitForExit(100); 
} 

私は問題はガベージコレクションについての何かだったと思います。私のオブジェクトは完全に収集されませんでした。

+0

洞察のために[この回答](http://stackoverflow.com/a/17131389/17034)をチェックしてください。 –

+0

ありがとう!あなたのアドバイスはうまく私のために働いた。だからあなたの正解を変えました。 – alisabzevari

関連する問題