2010-12-07 8 views
1

Visual Basic .NETアプリケーションからCOM相互運用機能を使用しているVB6で記述されたCOMコンポーネントがあります。なぜ私のCOMコンポーネントはOutOfMemoryExceptionをスローしますが、VB6では正常に動作しますか?

VB.NETから呼び出されたときにOutOfMemoryExceptionをスローするメソッドがあります。しかし、Visual Basic 6アプリケーションから全く同じ呼び出しを実行すると、すべて正常に動作します。

私はVB6からデバッグしようとするとエラーが発生しないため、これは長すぎるし、フォローするのが難しい(私はそれを修正することが任されている)表示されます。

この動作が異なる原因は何ですか?

辞書オブジェクト(Microsoft Scripting RuntimeのCOM)を使用してパフォーマンスの問題を修正するまで、これはうまくいきました。ディクショナリが非合理的に成長したり漏れない限り、例外がスローされる前にディメンションが100〜200の要素を超えることはなく、1つしか作成されないため、ディクショナリがこの原因となる可能性はありません。

私はCollectionオブジェクトと厄介なExists()関数で同じ修正を試みましたが、同じ問題が発生します。 Nothingを返すことで早期に救済できれば、それは動作します(つまり、NullReferenceExceptionがスローされます)。

+0

意味のあるスタックトレースはありますか?メモリについてはどうですか?プロセスのサイズはどれくらいですか? –

+0

@Simon:stacktraceはCOM/.NET境界で終了します。例外がスタックを横切って飛ぶと、プロセスは約100メガになります。 –

+0

Scripting.Dictionary COMオブジェクトはSTA(Apartment)としてマークされています。以下にweloyttyが述べたように、スレッドをチェックしましたか?そして、あなたは複数のスレッドを使ってこの辞書にアクセスしていますか? –

答えて

1

VB.NETでのメモリ管理は非常に異なります。 VB6は参照カウントを使用してCOMオブジェクトを解放し、VB.NETはガベージコレクタを使用します。特に、GCがCOMオブジェクトを解放するのに十分頻繁に実行されないコンポーネントをユニットテストするときは、状況に陥る可能性があります。これらのオブジェクトは、コレクションを開始するためにガベージコレクタに圧力をかけることはありませんが、アンマネージメモリを割り当てます。

これはPerfmon.exe、Performance Monitorで診断を開始します。グラフを右クリックして[カウンタを追加]を選択し、[.NET CLRメモリ]、[Gen 0コレクション]を選択し、プロセスを選択します。妥当な割合でカウンタが1秒以上に増加していることを確認します。

このような問題を解決することはかなり不愉快です。これはコンポーネントを分離することによって引き起こされる人為的な問題ではないことを確認してください。 COMオブジェクトへの参照を保持して、コード内の普通のバグ。 GC.Collect()の後にGC.WaitForPendingFinalizers()を呼び出すと、COMオブジェクトが解放されます。 Marshal.ReleaseComObject()も同様に呼び出します。 GC.AddMemoryPressure()を使用することも考えられますが、COMオブジェクトに必要な管理されていないメモリの量を考えなければなりません。

+0

COMオブジェクトへの参照を保持することによるバグは、コードの.NET部分に触れなかったためそうではありません。 perfmonを使用すると、実行中のコレクションはほとんど見られませんでした。投げられる前にGen 0のコレクションが10個しかなく、Gen 2のコレクションが2個しかありませんでした。今のところ、パフォーマンスの修正を.NETレイヤーにプッシュすることで問題を解決しました... –