2009-03-13 14 views
0

ワーカースレッドでCOMオブジェクトを使用するマルチスレッドアンマネージドアプリケーションを作成しました。 COMとしてエクスポートされた.NETオブジェクトを使用して作業を開始するまでは、すべてうまく行きました。COM&C#を使用したマルチスレッドアプリケーションでメモリリークが発生する

.NETオブジェクトの機能の一部をコメントとして取り上げ、.NETオブジェクト内からCOMオブジェクトを使用する方法まで説明しました。要約すると:

  1. 私のプログラムは、いくつかのワーカースレッドを開始します。
  2. 各ワーカースレッドは、作業を行うために.NETベースのCOMオブジェクトを初期化します。
  3. .NETベースのCOMオブジェクトは、アンマネージCOMオブジェクトを内部的に使用します。

驚いたことに、OutOfMemory例外が表示されるまで、アプリケーションのメモリ消費が着実に上昇し始めました。私はこの機能をコメントアウトした場合

void DoSomeWork() 
{ 
    IComObject O = new ComObjectClass(); 
    try 
    { 
     // do something 
    } 
    finally 
    { 
     Marshal.ReleaseComObject(O); 
    } 

} 

、メモリリークが消える:

は、ここに私の.NET実装です。 GC.Collect()を呼び出すと、メモリリークが発生します。

何が起こっているのでしょうか?

EDIT:コメントや回答に基づいていくつかの詳細情報:

  1. 作成されたすべてのスレッドがMTAで実行されています。
  2. すべてのCOMオブジェクトはIMarshalを実装し、フリースレッドマーシャラを使用します。
  3. 何が何であるかは関係ありません。int i = 0; i ++;漏れを生成する。
  4. ComObjetClassが指摘するオブジェクトは古いものであり、テストされています。これは、それが欠陥ではないことを意味するものではありませんが、眩しいものではありません。
  5. 私は、メインスレッドと別の作成されたスレッドの両方でC#プログラムからCOMオブジェクトを繰り返し作成しようとしました。どちらの場合も、メモリリークは消えました。管理されていないコードから管理されたコードへのクロスとバックは不可欠です。それを削除すると、問題が消えてしまいます。
+0

何が//何かにありますか?場合によっては、アンマネージコードで作成された新しいオブジェクトがあります。 – Grzenio

+0

"do smth"では、2つのCOMオブジェクトを一緒に接続すると、メモリリークが発生する危険性があります。コードは何が起こっているのかを理解するのに役立ちます。 – sharptooth

+0

問題が実際にCOMオブジェクトクラスにある場合はどうでしょうか?それは間違った参照カウントメカニズムを持っているのですか?それを他のCOMオブジェクトに置き換えるとどうなりますか? – sharptooth

答えて

2

COMラッパーオブジェクトをSTAスレッドに切り替えてファイナライズする必要がある可能性があります。 STAがメッセージをポンピングしない場合、これは決して起こりません。したがってファイナライズは決して呼び出されず、メモリリークが発生します。

さらに詳しい情報はthis KBです。

0

こんにちは、コードの平和を使用することをお勧めします。

 if (feature != null) 
     { 
      while (Marshal.ReleaseComObject(feature) > 0) 
      { } 
      feature=null; 
     } 

comオブジェクトを参照型として使用している場合。例。カーソル。 あなただけの場合 Marshal.ReleaseComObject(O);

1つの参照と残りの参照のみがメモリ内に保持されるので、すべての参照を解放する方がよいでしょう。

関連する問題