2

最近、.netアプリでさまざまなテストを実行して、メモリフットプリントをどのように抑えることができるかを確認しました。管理されていないリソースの破棄、イベントの登録解除、xamlリソースでのFREEZEの使用など、さまざまなヒントやガイドラインに出くわしました。これらはすべて理にかなっています。ほとんどのものはすでに処理されているので、メモリ消費量は同じままでした。ただし、現在の実行でこれまで開かれたことがない新しいウィンドウはそれぞれ、より多くのメモリを消費し、ウィンドウを閉じた後に元に戻らないように見えることがわかりました。

そこで、デバッグ目的でウィンドウを閉じた直後にGC.Collect()を実行しましたが、成功しませんでした。

アプリにはAllowsTransparency=trueのウィンドウがいくつかあったので、属性を削除すると、メモリに大きな違いが見られました。約5 MB少なくなりましたが、ウィンドウを閉じた後も、ウィンドウが現在使用していたメモリは解放されませんでした。問題は同じままでした。これがサンプルです

C#

Window w;
bool isWindowOpen = false;
private void Button_Click(object sender, RoutedEventArgs e)
{

   if (!isWindowOpen)
   {
     w = new Window();
     isWindowOpen = true;

     // turn off the following two lines to see a noteable difference.
     w.AllowsTransparency = true; 
     w.WindowStyle = WindowStyle.None;

     //Even when the transparency is set to false, the memory increased by the new 
     //Window will never be returned. Try making the window a little bit heavier by
     //adding a few buttons and combos and clicking them rapidly before closing the 
     //window.

     w.Show();
   }
   else
   { w.Close(); isWindowOpen = false; GC.Collect(); 
    //Console.WriteLine(GC.GetTotalMemory(true).ToString());
    //Console.WriteLine(GC.CollectionCount(0).ToString());
   }
 }

CLR / WPFの第一人者はこれを説明できますか?透明なウィンドウを閉じた直後にGCを強制的に実行して、消費したすべてのメモリを解放する方法は絶対にありませんか?GCは後で必要になったときに実行される可能性があることは理解していますが、結局のところ、タスクマネージャーはすべてクライアントが取得するものであり、マニアックな人もいます。

4

1 に答える 1

3

Kernal32dllが私の問題の答えであることがわかりました。

[DllImport("kernel32.dll")]
private static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);

SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);

値が-1のSetProcessWorkingSetSizeは、プロセスに対して可能な限り多くのページを削除し、タスクマネージャーの数値が大幅に低下します。ただし、パフォーマンスにどのような影響があるかはわかりませんが、私のアプリにとっては完璧です。

于 2012-03-07T08:00:08.053 に答える