2011-04-25 72 views
1

警告:這是我第一個'真正'的WPF應用程序。我確定這是一個邏輯錯誤,我有一個地方,但無法弄清楚我應該在哪裏尋找。WPF Window.Close內存泄漏

我有一個自助服務終端類型的應用程序,循環通過各種窗口,每個窗口顯示不同類型的數據。我(目前)通過一個定時器來控制它們,並且應用程序運行良好,直到我最終達到內存不足異常。

我的代碼通過Windows轉動如下:

private Window activeWindow; 

private void ShowNextTaskWindow(ITask task) { 

    Window nextWindow = windowManager.GetWindowForTask(task); 

    nextWindow.Show(); 

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

} 

的窗口管理類只實例化窗口的適當類型 - 即NewsWindow或視頻窗口,根據任務類型:

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()應該擺脫窗口,所以我迷失在哪裏尋找問題。

任何想法?

+0

你確定不是泄漏內存的窗口中的控件之一嗎?如果您使用空窗口運行應用程序,是否會發生內存不足異常? – 2011-04-25 19:35:23

+0

你的窗口是否擁有非託管資源?考慮使用MVVM設計模式 - 您當前的體系結構不是非常WPF風格的。 – 2011-04-25 20:17:46

+0

非常像這個http://stackoverflow.com/questions/2860965/wpf-memory-leak的答案,我發現一個案例,我確實有一個事件處理程序,用戶沒有正確處理。我已經修復了 - 但總體而言,仍然遭受同樣的問題。如果我想知道*我正在「做錯了」,那就去看MVVM吧。謝謝,@Danny Varod – reallyJim 2011-04-26 21:59:28

回答

0

你真的應該使用CLR Profiler找出哪些對象,泄漏,消除了泄漏源...

但我也要去建議,假設你通過少量的循環ITasks,重用您的Window實例可能是個好主意。在GetWindowForTask中,可以使用字典(可能是ConditionalWeakTable)將Windows與任務相關聯。如果任務已經有一個窗口,只需返回它,不要實例化一個新的窗口。

根據實際發生的情況,重複使用Windows可能會「阻止泄漏」(儘管您仍應該找出解決方法並以正確的方式解決問題)。

+0

是的,我和你在一起。目前重寫爲MVVM,目的是儘可能重用。雖然沒有使用過該工具,但會嘗試運行該應用程序。謝謝! – reallyJim 2011-04-28 19:21:25

0

當您在nextWindow上調用.Show()時,它會導致activeWindow不可見,因此當您調用Close()時,activeWindow不會處理它的控件。

關閉()文件中的註釋部分明確提到這樣的場景: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx

+0

你的鏈接引用winforms,而OP使用WPF窗口不知道WPF窗口是否遭受同樣的問題。 – ChrisWue 2011-04-25 23:45:22

0

要找到「泄漏」你必須首先做一些分析。

  1. 通過測試程序並使用單一類型的窗口來查找導致泄漏的窗口。讓程序運行直到失敗,或者您確定此窗口類型不會導致任何問題。對所有類型重複此操作。
  2. 找到有問題的窗口類型後,檢查其代碼並逐個關閉/打開功能以查找問題。
+0

我看到了所有窗口類型的行爲 - 它並不侷限於單一窗口類型。 – reallyJim 2011-04-26 21:55:44