2

.NET アプリケーションにコア機能を提供する C++ ライブラリ (MFC なし、ATL なし) があります。C++ DLL は、PInvoke を使用してそのクラス/メソッドにアクセスするために使用できる C# アセンブリを生成するためにSWIGによって使用されます。この C# アセンブリは、.NET アプリケーションで C++ DLL 内の機能を使用するために使用されます。

この問題は、メモリ リークに関連しています。私たちの .NET アプリケーションでは、C++ DLL から特定のクラスの何千ものインスタンスを作成する .NET コードにループがあります。ループはインスタンスを作成するにつれて遅くなり続けますが、ループ内で GC.Collect() を呼び出すと (これはお勧めできません)、処理が速くなります。どうしてこれなの?型で Dispose() を呼び出しても、速度には影響しません。GC.Collect() を使用するとプログラム速度が低下することを期待していましたが、それは正反対です。

SWIG が生成する各クラスには、Dispose() を呼び出す ~destructor があります。すべての Dispose メソッドには、アンマネージ メモリを破棄する呼び出しを行うステートメントの周りに lock(this) があります。最後に GC.SuppressFinalize を呼び出します。また、リリース ビルドでは AccessViolationException が散発的に発生します。どんな助けでも大歓迎です。

4

2 に答える 2

1

一部のタイプのオブジェクトはFinalize、破棄されずに破棄された場合、( を介して) 自分自身の後にクリーンアップできますが、ファイナライザーがそれらに到達するまで維持するのにコストがかかる可能性があります。フレームワーク内の 1 つの例は、によって返される列挙子Microsoft.VisualBasic.Collection.GetEnumerator()です。を呼び出すたびGetEnumerator()に、新しい列挙子オブジェクトによってラップされたオブジェクトが、コレクションによって管理されるさまざまなプライベート更新イベントにアタッチされます。列挙子がDisposed の場合、そのイベントのサブスクライブが解除されます。もしもGetEnumerator()列挙子が破棄されず、ガベージ コレクションが介在することなく、何度も (たとえば、数千または数百万回) 呼び出されると、イベント サブスクリプション リストが大きくなり続けるにつれて、コレクションはますます遅くなります (通常よりも数百倍または数千倍遅くなります)。ただし、ガベージ コレクションが発生すると、放棄された列挙子のFinalizeメソッドはサブスクリプションをクリーンアップし、正常に機能し始めます。

を呼び出しているとおっしゃっていましたが、何かがオブジェクト インスタンスをDispose作成していて、それを呼び出していないのではないかと疑っています。classがclassのインスタンスを作成して所有しているが、そのインスタンスが独自の実装内にない場合、 のインスタンスを呼び出しても. のインスタンスが破棄されると、それが d であるかどうかにかかわらず、破棄されずに破棄されます。IDisposableDisposeIDisposableFooIDisposableBarFooDisposeDisposeDisposeFooBarFooDisposeBar

于 2012-09-21T18:00:17.393 に答える
0

Dispose メソッドで GC.SupressFinalize を呼び出していますか? とにかく、GCフレンドリーなコードの書き方-ガベージコレクションの基本とパフォーマンスのヒントを説明する素晴らしいMSDN記事があります。多分それは役に立つでしょう。

于 2012-09-20T06:03:12.877 に答える