我正在从事一个大规模项目,其中提供了一个自定义(相当强大)的框架,我们必须将其用于显示表格和视图。


每当打开新的策略形式时,就会有抽象类策略编辑器(从框架中的某些类中得出)。

StrategyForm (自定义窗框)包含 StrategyEditor.
StrategyEditor 包含 StrategyTab.
StrategyTab 包含 StrategyCanvas.

这是大型类的一小部分,可以澄清如果在运行时将一个策略形式对象分配在内存中,将创建许多对象。我的组件拥有上面提到的所有这些类,除了 StrategyForm 我的代码不在我的控制中。


现在,在运行时,用户打开了许多策略对象(这些对象触发了新的策略形式对象。)创建大约。 44策略对象,我们看到该应用程序创建的用户对象搬运(我将从此处使用UOH)达到约20K+,而在注册表中,hanger的默认金额为10k。 在此处阅读有关用户对象的更多信息。 在不同的机器上进行测试清楚地表明,打开的策略对象的数量对于弹出消息是不同的 - 在一个m/c上,如果是44,则可以在另一个m/c上为40。

当我们看到消息弹出窗口时,这意味着应用程序将响应缓慢。更糟的是,几乎没有对象,然后创建窗口框架和后续对象失败。

我们首先认为这不是记忆问题。但是之后 阅读更多有关 new 在C#中 有助于理解如果应用程序用完了记忆,将会抛出一个例外。我觉得这不是内存问题(任务管理器还显示1.5GB+可用的内存。)


M/C规格
核心2二重奏2GHz+
4GB RAM
80GB+页面文件的免费磁盘空间
虚拟内存集:4000-6000


我的问题


Q1。这看起来像一个记忆问题,我错了吗?
Q2。这是否指出了自由UOHS的精疲力尽(正如我所想的)以及哪些导致窗户手柄的创建失败?
Q3。我们如何避免加载 StrategyEditor 对象(超出阈值,关注当前的UOH使用)? (我们已经知道如何获取使用的UOH数量,所以不要去那里。) 请记住呼吁 new StrategyForm() 不在我的组件的控制之外。
Q4。我有点困惑 - 什么是 处理用户对象 确切地? MSDN是在谈论我们创建的任何对象还是仅仅是某些特定对象,例如窗口手柄,光标手柄,图标手柄?
Q5。是什么导致uoh消耗的是什么? (几乎与Q4相同)

我真的很感谢任何能给我一些知识渊博的答案的人。非常感谢! :)

更新
基于STAKX答案,请注意,要打开的窗口将仅由用户关闭。这是一种MDI应用程序的情况,打开太多儿童窗户的方式。所以, Dispose 我们想要时不能打电话。

有帮助吗?

解决方案

Q1

听起来您正在尝试同时创建太多的UI控件。即使剩下记忆,您的手柄也用尽。有关简短但相当技术的解释,请参见下文。

Q4

我了解一个 用户对象 成为GUI一部分的任何对象。至少在Windows XP之前,Windows UI API居住在 USER.DLL (组成窗口的核心DLL之一)。基本上,UI由“ Windows”组成。所有控件(例如按钮,文本框,复选框)在内部相同,即“ Windows”。要创建它们,您将调用Win32 API功能 CreateWindow. 。然后,该功能将返回创建的“窗口”(UI元素或“用户对象”)。

所以我认为 用户对象句柄 是此功能返回的句柄。 (Winforms基于旧的Win32 API,因此将使用 CreateWindow 功能。)

Q2

确实,您无法根据需要创建尽可能多的UI控件。所有这些手柄都通过 CreateWindow 必须在某个时候被释放。在Winforms中,最简单,最安全的方法是通过使用 using 块或打电话 Dispose:

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

基本上,全部 System.Windows.Forms.ControlDisposeD,应处置。有时,这是自动为您完成的,但是您不应该依靠它。总是 Dispose 当您不再需要它们时,您的UI会控制。

注意 Dispose 对于模态和无模型表格:

  • 模态形式(显示 ShowDialog) 是 不是 自动处置。如上所述,您必须自己执行此操作。
  • 无调表格(显示 Show)自动为您处理,因为您无法控制用户何时将其关闭。无需明确致电 Dispose!

Q5

每当您创建一个UI对象时,Winforms都会在内部拨打电话 CreateWindow. 。这就是分配的方式。直到对应的电话 DestroyWindow 是制造的。在Winforms中,该呼叫是通过 Dispose 任何方法 System.Windows.Forms.Control. (注意:虽然我很确定这一点,但我实际上是在猜测。我可能不是100%正确。使用反射器查看Winforms内部设备会揭示真相。)

Q3

假设你 StrategyEditor 创建大量的UI控件,我认为您不能做很多事情。如果您无法简化该控件(就其创建的儿童控制数量而言),那么您似乎陷入了自己的状态。你很简单 不能 创建无限的许多UI控件。

但是,您可以跟踪多少 StrategyEditors随时打开(每当实例化时增加一个计数器,并在关闭时降低它 - 您可以使用该柜台来跟踪后者 FormClosing/FormClosed 形式的事件,或 Dispose 控制方法)。那么您可以限制同时打开的数量 StrategyEditors到固定的数字,例如5。如果超过限制,则可以在构造函数中抛出异常,因此不再创建更多实例。我当然不能说是否 StrategyForm 要处理您的例外 StrategyEditor 构造函好...

public class StrategyEditor : ...
{
    public StrategyEditor()
    {
        InitializeComponent();

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

无论哪种情况,都限制实例化的数量 StrategyEditorS对我来说似乎是一个暂时的解决方案,不会解决真正的问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top