代码之家  ›  专栏  ›  技术社区  ›  Nayan

内存不足或句柄不足?

  •  1
  • Nayan  · 技术社区  · 16 年前


    有一个抽象类StrategyEditor(派生自框架中的某个类),每当打开一个新的StrategyForm时都会实例化它。

    StrategyForm (自定义窗框)包含 StrategyEditor .
    战略编辑 包含 StrategyTab
    战略选项卡 包含 StrategyCanvas .

    这是大型类的一小部分,用于说明如果在运行时在内存中分配一个StrategyForm对象,那么将创建许多对象。我的组件拥有上述所有类,除了 战略表 他的代码不在我的控制之下。


    现在,在运行时,用户打开了许多strategy对象(触发了新StrategyForm对象的创建)。在创建了大约44个strategy对象之后,我们看到应用程序创建的用户对象句柄(从这里开始我将使用UOH)达到了大约20k+,而在registry中,句柄的默认数量是10k。 Read more about User Objects here. 在不同机器上的测试表明,打开的策略对象的数量对于弹出的消息是不同的——在一个m/c上如果是44,那么在另一个m/c上可以是40。

    当我们看到弹出的消息时,这意味着应用程序将缓慢响应。如果对象太少,情况会变得更糟,然后创建窗口框架和后续对象就会失败。

    reading more about new in C# 有助于理解应用程序内存不足时会引发异常。我觉得这不是内存问题(任务管理器也显示了1.5GB+可用内存)


    M/C规格
    核心2 Duo 2GHz+
    4GB内存




    我的问题


    问题1。这看起来像是记忆问题吗?我错了,不是吗?
    问题2。这是否意味着自由uoh的耗尽(正如我所想的那样),并导致创建窗口句柄的失败?
    问题3。我们怎样才能避免装载货物 战略编辑 请记住 new StrategyForm() 在我的组件控制之外。
    第四季度。我有点困惑-你在说什么 用户对象的句柄
    问题5。到底是什么原因导致使用UOH(与第4季度几乎相同)

    [更新]
    根据Stakx答案,请注意,正在打开的窗口将仅由用户关闭。这是一种MDI应用程序的情况下,太多的儿童窗口被打开。所以, Dispose 不能随时打电话给我们。

    1 回复  |  直到 6 年前
        1
  •  2
  •   stakx - no longer contributing Saravana Kumar    16 年前

    第一季度

    听起来你想在同一时间创建太多的UI控件。即使还有内存,你的句柄也快用完了。下面是一个简短的,但相当技术性的解释。

    我了解一个 用户对象 USER.DLL CreateWindow . 然后,该函数将向创建的“窗口”(UI元素或“用户对象”)返回一个句柄。

    所以我假设 用户对象句柄 创建窗口 函数。)

    实际上,您不能创建任意多的UI控件。所有这些手柄都是通过 创建窗口 总有一天会被释放的。在Winforms中,最简单、最安全的方法是使用 using 阻止或通过呼叫 Dispose :

    using (MyForm form = new MyForm())
    {
        if (form.ShowDialog() == DialogResult.OK) ...
    }    
    

    基本上,所有 System.Windows.Forms.Control 处置 当您不再需要UI控件时,可以使用它们。

    上的注释 处置

    • 模态形式(以 ShowDialog )是吗 自动处理。您必须自己完成,如上面的代码示例所示。
    • Show )自动为您处理,因为您无法控制用户何时关闭它。不需要显式调用 处置 !

    问题5

    每次创建UI对象时,Winforms都会在内部调用 创建窗口 . 这就是句柄的分配方式。直到相应的调用 DestroyWindow 是制造的。在Winforms中,该调用是通过 任何方法 System.Windows.Forms.Control . (注:虽然我对此非常肯定,但实际上我只是猜测了一下。我可能不是100%正确。使用Reflector查看Winforms内部将揭示事实。)

    假设你的 StrategyEditor 不能 创建无限多的UI控件。

    不过,你可以记录下有多少人 在任何时候都会打开(实例化计数器时增加计数器,关闭计数器时减少计数器——您可以使用 FormClosing FormClosed 一种形式的事件,或 处置 控制方法)。然后您可以限制同时打开的 战略编辑 StrategyForm 将处理来自 战略编辑 好吧。。。

    public class StrategyEditor : ...
    {
        public StrategyEditor()
        {
            InitializeComponent();
    
            if (numberOfLiveInstances >= maximumAllowedLiveInstances)
                throw ...;
            // not a nice solution IMHO, but if you've no other choice...
        }
    }
    

    在这两种情况下,限制实例化的 这对我来说只是暂时的解决办法,并不能解决真正的问题。