Как сразу же освободить память в приложении WPF, чтобы она могла отражаться в TaskManager? - PullRequest
1 голос
/ 03 марта 2012

Недавно я запустил разные тесты в приложении .net, чтобы увидеть, как можно уменьшить объем памяти. Я сталкивался с различными советами / рекомендациями, такими как удаление неуправляемых ресурсов, отмена регистрации событий, использование FREEZE на ресурсах xaml и т. Д., И все это имело смысл. О большинстве вещей уже позаботились, поэтому потребление памяти осталось прежним. Однако я выяснил, что каждое новое окно, которое никогда ранее не открывалось в текущем цикле, будет занимать немного больше памяти и никогда не вернет его обратно после закрытия окна.

Итак, я запустил GC.Collect () сразу после закрытия окна для отладки, но безуспешно.

В приложении было несколько окон с AllowsTransparency = true, поэтому я удалил атрибут и увидел большую разницу в памяти, примерно на 5 МБ меньше! Так что проблема осталась прежней. Вот образец

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 может запускаться позже, когда это необходимо, но, в конце концов, диспетчер задач - это все, что получают клиенты, и есть также некоторые маньяки.

1 Ответ

1 голос
/ 07 марта 2012

Я обнаружил, что Kernal32 dll был ответом на мою проблему.

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

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

SetProcessWorkingSetSize со значениями -1 удалит столько страниц, сколько это возможно для процесса, а цифры менеджера задач резко сократятся. Тем не менее, я не знаю, какой у него удар по производительности, но для моего приложения он идеален.

...