4

オブジェクトへの余分な弱参照を保持し、解放する必要があるときにオブジェクトがアクティブでなくなったことを確認することで、コードでメモリリークが発生しないようにプロアクティブに確認しようとしています(これは条件付きコードであるため、テスト中です)。

私が見ている効果を簡単に再現するには、新しいWPFアプリケーションを作成し、メインウィンドウにボタンを配置します。別のウィンドウを作成し、その上にTextBoxを配置します。ボタンのクリックハンドラーに、次のコードを入力します。

  Window1 w = new Window1();
  WeakReference weak = new WeakReference(w);
  w.ShowDialog();
  w = null;
  // Equivalent to Application.DoEvents() just in case...
  Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
  GC.Collect();
  GC.WaitForPendingFinalizers();
  if (weak.Target != null)
    MessageBox.Show("Memory Leak");

これを実行するときは、ボタンをクリックし、ウィンドウが表示されたら、「x」をクリックして閉じます。何も起こりません。すべて問題ありません。同じことを行いますが、ウィンドウが表示されたら、TextBoxをクリックしてから、「x」をクリックします。毎回「メモリリーク」メッセージが表示されます。

Ants Profilerは、System.Windows.Documents.TextEditorにTextBoxへの参照があり(おそらく、TextBoxにフォーカスした場合にのみ設定されます)、TextBoxにウィンドウへの参照があることを示しています。プロセスを複数回実行すると、最新ではなく以前のウィンドウが収集されるため、実際のメモリリークではありません。ただし、メモリがリークしていないことを確認するテストを作成できないことを意味します。

このレベルの保証を望んでいるのは私だけですか、それとも別の方法がありますか?

4

4 に答える 4

2

ご質問の趣旨を誤解されている方もいらっしゃると思います。あなたは GC の手を強制しようとしているのではなく、メモリ リークを事前に発見しようとしているのです。

この特定のケースでは、TextEditor(これはinternal) イベント ハンドラーを追加しているように見えますが、チェックの実行時にまだデタッチする機会がありません。ディスパッチャーをポンピングする前に、閉じたウィンドウから明示的にフォーカスを移動しようとしましたか?

統合テストのより制御された環境ではなく、適切なアプリケーションでこれらのテストを実行しようとすると、この種の問題に引き続き遭遇すると思うので、おそらくアプローチを再考する必要があります。

于 2012-06-25T08:50:13.093 に答える
0

以前のインスタンスが収集された場合、それはメモリ リークではありません。ガベージ コレクターは、常に最新のアイテムを取得するとは限りません。これは設計によるものです。もう一度推測しようとすると、問題が発生する可能性があります。

実際のメモリ リークでは、再利用されることなくアイテムが蓄積されます。これは、プロファイラーを使用して検出するのが最適です。

于 2012-06-25T02:01:10.680 に答える
0

DispatcherPriority で試してください。コンテキストアイドル

Dispatcher.CurrentDispatcher.Invoke( DispatcherPriority.ContextIdle, new System.Action(delegate { }));
于 2012-10-03T17:58:24.357 に答える
0

Windows はコードによって管理されるだけでなく、Application. 呼び出しCollectは何も保証または証明しません。ウィンドウは最終的に収集されます。

于 2012-06-25T02:18:09.457 に答える