【问题标题】:Clear controls does not dispose them - what is the risk?明确的控制并不能消除它们——风险是什么?
【发布时间】:2010-12-30 11:51:43
【问题描述】:

有多个线程(abc 等)关于 Clear() .NET 组件容器中的项目不 Dispose 他们(通过调用 Dispose(true)。

恕我直言,大多数情况下,应用程序中不再使用已清除的组件,因此需要在从父容器中清除它们后显式处置。

也许集合的Clear 方法有一个布尔参数dispose 是个好主意,当它为true 时也会在集合元素从列表中删除之前对其进行处置?

【问题讨论】:

  • 如果在终结器中有对 Dispose 的调用,它们将被释放。如果没有,那么可能(如果程序员遵循公认的做法)没有任何无法处理的东西,只是垃圾收集它们是安全的。
  • @Aviad:Dispose方法永远不会被GC调用的问题,所以你需要自己做,然后再调用Clear on collection。
  • 我的意思是,如果控件的程序员没有在其终结器中放置 Dispose 调用(当对象被垃圾回收时调用) - 那么可能没有任何东西可以释放。
  • 这里也可以看Hans对问题的详细描述:stackoverflow.com/a/2014427/366904

标签: .net garbage-collection components dispose


【解决方案1】:

@Hans Passant 的回答很好,但在异步编程的情况下,您应该考虑在释放对象之前删除它,以避免某些线程迭代已释放的对象。

或多或少是这样的:

public static class ExtensionMethods {
  public static void Clear(this Control.ControlCollection controls, bool dispose) {
    for (int ix = controls.Count - 1; ix >= 0; --ix) {
      var tmpObj = controls[ix];
      controls.RemoveAt(ix);
      if (dispose) tmpObj.Dispose();
    }
  }
}

【讨论】:

    【解决方案2】:

    回答“风险是什么”的问题时,风险(或风险)已用尽窗口句柄,尽管可能需要一段时间。

    我有一个从脚本生成窗口的“窗口设计器”。每次我更改脚本时,都会重建窗口(清除并读取控件)。对于一个特别复杂的窗口,并且每次都使用Controls.Clear(),经过几十次刷新,我最终会得到一个“没有更多窗口句柄”的异常,并且无法再创建任何控件。

    很容易将Controls.Clear() 调用替换为:

    Controls.Cast<Control>().ForEach(c => c.Dispose());
    

    【讨论】:

      【解决方案3】:

      要求这样的修改是没有意义的,Windows Forms 团队已经解散了很久。它处于维护模式,仅考虑安全问题和操作系统不兼容问题。

      创建自己的方法来执行此操作很简单:

        public static class ExtensionMethods {
          public static void Clear(this Control.ControlCollection controls, bool dispose) {
            for (int ix = controls.Count - 1; ix >= 0; --ix) {
              if (dispose) controls[ix].Dispose();
              else controls.RemoveAt(ix);
            }
          }
        }
      

      现在你可以写了:

        panel1.Controls.Clear(true);
      

      【讨论】:

      • IIRC,当你 DisposeControl 时,它会自动从对应的 ControlCollection 中删除控件,所以你实际上不需要 RemoveAt (并且可能最终得到一个IndexOutOfRangeException).
      • 是的......至少对于 .NET 2 这不起作用。但问题有点不同。在没有 Dispose 的情况下调用“Clear”是否存在“风险”?
      • 当然,您会泄露控件。从其他线程看不是很明显吗?
      • 呃,我没这么说。事实上,我认为 Clear() 总的来说没有多大意义。 WF 被优化为使用 UserControls 和设计器。容器控件已经知道如何正确处置其子控件。
      • 释放控件会自动释放其 Controls 集合中的任何子控件。不需要帮助。
      猜你喜欢
      • 2011-03-31
      • 2011-07-20
      • 2015-04-01
      • 2011-03-14
      • 1970-01-01
      • 2018-09-11
      • 2011-12-30
      • 2010-11-19
      • 2017-06-17
      相关资源
      最近更新 更多