2011-03-29 21 views
0

在WinForms應用程序中,我有多個實例將控件添加到容器以響應用戶操作(panel.Controls.Add(new CustomControl(...))),然後再清除面板(panel.Controls.Clear())並重新使用它。清除容器的Controls屬性並確保控件正確處置的最安全方法是什麼?

在生產中,應用程序偶爾會拋出一個與GDI錯誤或未能加載ImageList相關的異常。這通常發生在資源有限的計算機上,以及在一天中密集使用應用程序的用戶。這似乎很明顯,我有一個GDI處理泄漏,我應該處置從容器中清除的控件,但是我能找到的任何解釋都不清楚控件何時何地處理。

清除容器後應立即處理子控件嗎?喜歡的東西:

var controls = new List<Control>(_panel.Controls.Cast<Control>()); 
_panel.Controls.Clear(); 
foreach (var c in controls) c.Dispose(); 

或者我應該跟蹤控制在一個列表,並調用處理容器的Dispose()方法?如:

List<Control> _controlsToDispose = new List<Control>(); 
void ClearControls() 
{ 
    _controlsToDispose.AddRange(_panel.Controls.Cast<Control>()); 
    _panel.Controls.Clear(); 
} 
void Dispose() 
{ 
    ... 
    foreach (var c in _controlsToDispose) c.Dispose(); 
} 

回答

0

(有點有效)糾正在我的應用程序不是處置清除控件的任何情況後,我可以拿出一些要點:

  • 有時候,我已經預先建立一個列表控件,例如存儲在ListViewItem s或TreeViewItem s的集合的Tag財產中。他們不應該被清楚地處理,但整個列表應該迭代並且在父母的Dispose()方法中調用((Control)item.Tag).Dispose()
  • 如果控件不再被使用,當我在飛行中創建時會發生這種情況,它應該在從容器中清除時處理。
  • 清理和添加控件時,您需要考慮控件的生命週期以確定是否立即處理它們,請將其推遲到父項處置完畢或不擔心。
  • 我有一種情況,我刪除了一個控件以顯示'正在加載...'消息,然後在稍後將控件撤回,以響應線程完成。我在刪除控件時添加了一個調用來處理該控件,這會在嘗試再次添加控件時導致錯誤。由於線程問題,調試並不簡單。重點是生命週期可以依賴於UI線程以外的線程。這種情況恰恰相當於表格顯示後的20秒,所以至少控制權仍然存在。管理一個線程仍然希望引用它的控件可以被銷燬的情況可能是一個弱事件的例子。

我一直沒能找到有關管理生命週期的控制和處置的最佳做法或建議。我想這個規則就是,如果一個控件沒有結束它的生命套件,而是嵌套在一個處理過的控件上,那麼它必須手動處理,無論什麼時候它不再被使用,或者在父控件的方法Dispose()處最新的。

0

選項2介紹了另一份名單,你將需要清理,這將需要更多的內存用於這些項目。我更喜歡選擇1,並在你提到的代碼中包含try catch。

+0

所以沒有必要將控件放置在容器的Dispose()方法中?我可以在清除容器後儘快做到這一點? – 2011-03-29 09:54:13

相關問題