WPF Window.Закрыть утечку памяти - PullRequest
1 голос
/ 25 апреля 2011

Предупреждение: это мое первое «настоящее» приложение WPF. Я уверен, что это логическая ошибка, которая у меня где-то есть, но я не могу понять, где я должен искать.

У меня есть приложение типа киоска, которое циклически перебирает различные окна, каждое из которых отображает разные типы данных. Я (в настоящее время) управляю ими через таймер, и приложение работает хорошо, пока, наконец, не достигну исключения «Недостаточно памяти».

Мой код для поворота через окна выглядит следующим образом:

private Window activeWindow;

private void ShowNextTaskWindow(ITask task) {

    Window nextWindow = windowManager.GetWindowForTask(task);

    nextWindow.Show();

    if (activeWindow != null) {
        activeWindow.Close();
    }
    activeWindow = nextWindow;

}

Класс windowManager просто создает экземпляр соответствующего типа окна, то есть NewsWindow или VideoWindow, в зависимости от типа задачи:

public Window GetWindowForTask(ITask task) {

    Window taskWindow = null;

    switch (task.TaskType) {
            case TaskType.Web:
                taskWindow = new WebWindow(task as WebTask);
                break;

            case TaskType.Rss:
                taskWindow = new RssWindow(task as RssTask);
                break;

     ..... etc ......

    }
    return taskWindow;
}

Каждое окно имеет (только) один обработчик событий, добавленный в конструктор, например:

 Loaded += new RoutedEventHandler(Window_Loaded);

и, конечно, есть соответствующий метод Window_Loaded, который выполняет некоторую работу с макетом (настройка размеров окон, размеров элементов управления и т. Д.).

Проблема, с которой я столкнулся, заключается в том, что приложение просто продолжает потреблять память до тех пор, пока оно, наконец, не завершится с исключением «Недостаточно памяти» - и я не могу понять, где что-то упущено.

Насколько я понимаю, вызов Window.Close () должен избавиться от окна, поэтому я теряюсь в том, где искать проблему.

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 26 апреля 2011

Чтобы найти «утечку», сначала вам нужно выполнить некоторое профилирование.

  1. Найдите окна, которые вызывают утечку, протестировав программу и используя окно только одного типа. Дайте программе работать до тех пор, пока она не выйдет из строя, или вы уверены, что этот тип окна не вызывает никаких проблем. Повторите это для всех типов.
  2. После обнаружения проблемных типов окон изучите их код и включите / выключите функции одну за другой, чтобы найти проблему.
0 голосов
/ 28 апреля 2011

Вы действительно должны использовать CLR Profiler , чтобы выяснить, какие объекты протекают и устранить источник утечки ...

Но я также собираюсь рекомендовать это, если выциклически проходя через небольшое количество ИТ-задач, было бы неплохо повторно использовать ваши Window экземпляры.В вашем GetWindowForTask вы можете использовать словарь (может быть ConditionalWeakTable ), чтобы связать Windows с задачами.Если у Задачи уже есть Окно, просто верните его, не создавайте нового экземпляра.

В зависимости от того, что на самом деле происходит, повторное использование Windows может «остановить утечку» (хотя вам, вероятно, все равно придется это выяснитьи решить это правильно).

0 голосов
/ 25 апреля 2011

Когда вы вызываете .Show () для nextWindow, это делает activeWindow невидимым, поэтому activeWindow не располагает его элементами управления при вызове Close ().

В документации Close () этот сценарий явно упоминается вРаздел замечаний: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx

...