WPF RichTextBoxのメモリリーク
-
06-07-2019 - |
質問
私のアプリケーションには、実行時に動的に作成されるRichTextBoxがたくさんあります。 RichTextBoxコントロールが原因で、アプリケーションにメモリリークがあることがわかりました。コントロールが原因でメモリリークが発生することを証明するために、次のテストメソッドを作成しました。
for (int i = 0; i < 3000; i++)
{
Control rich = new RichTextBox();
pnl.Content = rich;
}
GC.Collect();
GC.WaitForPendingFinalizers();
pnl は、Xamlコードで宣言されているContentControlです。
次のコードを実行すると、メモリ使用量が急速に増加していることがわかります。
問題を解決する方法はありますか? オブジェクトプールを作成することを検討しましたが、これによりアプリケーションが複雑になり、むしろ避けます。
edit :オブジェクトがガベージコレクションされないことを示すために、ガベージコレクターへの呼び出しを追加しました。GCcollectメソッドの呼び出しの有無にかかわらず、メモリ使用量の改善はありません。
ループ内で rich.Dispose
を呼び出すと、メモリ使用量の増加がなくなります。
解決
これは他の場所で見つかりましたが、私のテストに関する限りは正しいようです。
FlowDocumentが作成されると、 比較的高価なフォーマット コンテキストオブジェクトも作成されます 構造キャッシュ内にあります。あなたが タイトに複数のFlowDocを作成する ループ、StructuralCacheが作成されます 各FlowDoc。あなたに電話しましょう ループの終わりにGc.Collect、 いくつかのメモリを回復したいと考えています。 StructuralCacheにはファイナライザーがあります この書式設定コンテキストを解放しますが、 すぐではありません。ファイナライザー 効果的に操作をスケジュールします コンテキストを解放 DispatcherPriority.Background。
したがって、ケースのRichTextBox(またはFlowDocument)は、クリーンアップするためにバックグラウンドスレッドを待機しているだけではリークしていません。正確に誰が知っているかを実行するとき。これがただちにクリーンアップを強制するdisposeメソッドを実装したことを望みます。
他のヒント
これは、アプリケーションにメモリリークがあることを示すものではなく、アプリケーションが多くのメモリを使用していることを示すものです 。 RichTextBox
コントロールが範囲外になった後、ある時点で解放されない場合、リークです(管理対象オブジェクトでのメモリリークの検出は、悪名高く、証明不可能です)。
オブジェクトがスコープから外れると、ガベージコレクションが行われるという一般的な誤解。これにより、収集対象が適格になります。オブジェクトは、理論的には、アプリケーションが終了するまで収集されることはありません。 RichTextBox
で成長し、他のコントロールでは成長しないという事実は、 RichTextBox
にメモリリークがあることを示すものではありません。他のコントロールよりもインスタンス。この情報は有用かもしれませんが、メモリリークがあるかどうかを判断するのには役立ちません。
winforms 2.0でも同じ問題があり、サードパーティのリッチテキストコントロールを購入する必要がありました。マイクロソフトはそれを修正する気にならなかったと思います...
これにより問題が修正されました。 http://blingcode.blogspot.com/2010/10 /memory-leak-with-wpfs-richtextbox.html
基本的に、各RichTextBoxに2つの属性を追加します:) :) IsUndoEnabled =&quot; False&quot;
編集について:
ループが終了し、3000個の RichTextBox
esがすべて作成された後、 GC呼び出しを追加しました。
前のループが新しいループに置き換えられたときにループ内で解放されないのは奇妙に思えますが、それは非常にタイトなループであるため、GCはおそらく「やること」をする機会を得られません;ループが終了する前。
良いアイデアとは思いませんが(テストコードでは問題ないはずですが)、GC呼び出しをループ内に移動しようとしましたか?