没有足够的内存或没有足够的句柄? [英] Not enough memory or not enough handles?

查看:95
本文介绍了没有足够的内存或没有足够的句柄?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个大型项目,其中提供了一个自定义(非常好且健壮)的框架,我们必须使用它来显示表单和视图.

I am working on a large scale project where a custom (pretty good and robust) framework has been provided and we have to use that for showing up forms and views.

有一个抽象类StrategyEditor(从框架中的某个类派生),只要打开新的StrategyForm就会实例化.

There is abstract class StrategyEditor (derived from some class in framework) which is instantiated whenever a new StrategyForm is opened.

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

StrategyForm (a customized window frame) contains StrategyEditor.
StrategyEditor contains StrategyTab.
StrategyTab contains StrategyCanvas.

这只是大型类的一小部分,以说明如果在运行时在内存中分配了一个StrategyForm对象,则会创建许多对象.我的组件拥有上述所有这些类,但StrategyForm的代码不在我的控制范围之内.

This is a small portion of the big classes to clarify that there are many objects that will be created if one StrategyForm object is allocated in memory at run-time. My component owns all these classes mentioned above except StrategyForm whose code is not in my control.

现在,在运行时,用户打开许多策略对象(这将触发创建新的StrategyForm对象).在44个策略对象中,我们看到由应用程序创建的用户对象句柄"(我将从此处开始使用UOH)达到约20k +,而在注册表中,句柄的默认数量为10k. 在此处了解有关用户对象的更多信息.不同的机器清楚地表明,为弹出消息而打开的策略对象的数量是不同的-在一个m/c上,如果是44,则在另一个m/c上可以是40.

Now, at run-time, user opens up many strategy objects (which trigger creation of new StrategyForm object.) After creating approx. 44 strategy objects, we see that the USER OBJECT HANDLES (I'll use UOH from here onwards) created by the application reaches to about 20k+, while in registry the default amount for handles is 10k. Read more about User Objects here. Testing on different machines made it clear that the number of strategy objects opened is different for message to pop-up - on one m/c if it is 44, then it can be 40 on another.

当我们看到消息弹出窗口时,这意味着该应用程序将响应缓慢.随着对象的增加,情况变得更糟,然后创建窗口框架和后续对象失败.

When we see the message pop-up, it means that the application is going to respond slowly. It gets worse with few more objects and then creation of window frames and subsequent objects fail.

我们首先认为这不是内存不足的问题.但是随后阅读有关C#中new的更多信息帮助了解如果应用程序内存不足将引发异常.我觉得这不是内存问题(任务管理器还显示了1.5GB +的可用内存.)

We first thought that it was not-enough-memory issue. But then reading more about new in C# helped in understanding that an exception would be thrown if app ran out of memory. This is not a memory issue then, I feel (task manager also showed 1.5GB+ available memory.)

M/C规格
Core 2 Duo 2GHz +
4GB RAM
页面文件80GB以上的可用磁盘空间
虚拟内存集:4000-6000


我的问题

M/C specs
Core 2 Duo 2GHz+
4GB RAM
80GB+ free disk space for page file
Virtual Memory set: 4000 - 6000


My questions

Q1.这看起来像是内存问题,不是吗?
Q2.这是否意味着用尽了免费的UOH(正如我在想的那样),并导致创建窗口句柄失败?
第三季度.我们如何避免加载StrategyEditor对象(超出阈值,关注UOH的当前使用情况)? (我们已经知道如何获取正在使用的UOH的数量,所以不要去那里.)请记住,对new StrategyForm()的调用不在我组件的控制范围之内.
Q4.我有点困惑-什么是用户对象的句柄? MSDN是在谈论我们创建的任何对象,还是仅谈论某些特定对象,例如窗口句柄,光标句柄,图标句柄?
Q5.造成UOH用完的确切原因是什么? (与第四季度几乎相同)

Q1. Does this look like a memory issue and I am wrong that it is not?
Q2. Does this point to exhaustion of free UOHs (as I'm thinking) and which is resulting in failure of creation of window handles?
Q3. How can we avoid loading up of an StrategyEditor object (beyond a threshold, keeping an eye on the current usage of UOHs)? (we already know how to fetch number of UOHs in use, so don't go there.) Keep in mind that the call to new StrategyForm() is outside the control of my component.
Q4. I am bit confused - what are Handles to user objects exactly? Is MSDN talking about any object that we create or only some specific objects like window handles, cursor handles, icon handles?
Q5. What exactly causes to use up a UOH? (almost same as Q4)

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

I would be really thankful to anyone who can give me some knowledgeable answers. Thanks much! :)

[更新]
根据Stakx的答案,请注意,正在打开的窗口将仅由用户关闭.这是一种MDI应用程序情况,其中打开了太多子窗口.因此,无论何时我们都无法调用Dispose.

[Update]
Based on Stakx answer, please note that the windows that are being opened, will be closed by the user only. This is kind of MDI app situation where way too many children windows are opened. So, Dispose can not be called whenever we want.

推荐答案

Q1

听起来像您正在尝试同时创建太多UI控件.即使有剩余的内存,您也将耗尽句柄.请参阅下面的简短但相当技术性的解释.

Q1

Sounds like you're trying to create far too many UI controls at the same time. Even if there's memory left, you're running out of handles. See below for a brief, but fairly technical explanation.

我知道用户对象是GUI内的任何对象.至少在Windows XP之前,Windows UI API驻留在USER.DLL中(构成Windows的核心DLL之一).基本上,UI由窗口"组成.所有控件,例如按钮,文本框,复选框,在内部都是相同的东西,即窗口".要创建它们,您可以调用Win32 API函数 CreateWindow .然后,该函数将返回创建的窗口"(UI元素或用户对象")的句柄.

I understand a user object to be any object that is part of the GUI. At least until Windows XP, the Windows UI API resided in USER.DLL (one of the core DLLs making up Windows). Basically, the UI is made up of "windows". All controls, such as buttons, textboxes, checkboxes, are internally the same thing, namely "windows". To create them, you'd call the Win32 API function CreateWindow. That function would then return a handle to the created "window" (UI element, or "user object").

因此,我假设用户对象的句柄是此函数返回的句柄. (Winforms基于旧的Win32 API,因此将使用CreateWindow函数.)

So I assume that a user object handle is a handle as returned by this function. (Winforms is based on the old Win32 API and would therefore use the CreateWindow function.)

实际上,您无法创建所需数量的UI控件.通过CreateWindow检索的所有那些句柄必须在某个时候释放.在Winforms中,最简单,最安全的方法是使用using块或调用Dispose:

Indeed you cannot create as many UI controls as you want. All those handles retrieved through CreateWindow must at some point be freed. In Winforms, the easiest and safest way to do this is through the use of the using block or by calling Dispose:

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

基本上,所有System.Windows.Forms.Control都可以是Dispose d,应将其处置.有时,这是自动为您完成的,但您不应该依赖它.当不再需要它们时,请始终Dispose您的UI控件.

Basically, all System.Windows.Forms.Control can be Disposed, and should be disposed. Sometimes, that's done for you automatically, but you shouldn't rely on it. Always Dispose your UI controls when you no longer need them.

关于Dispose的模式&注释非模式形式:

Note on Dispose for modal & modeless forms:

  • 模态形式(用ShowDialog表示)不会自动处理.如上面的代码示例所示,您必须自己做.
  • 无模式表单(用Show显示)会自动为您处理,因为您无法控制用户何时关闭表单.无需显式调用Dispose
  • Modal forms (shown with ShowDialog) are not automatically disposed. You have to do that yourself, as demonstrated in the code example above.
  • Modeless forms (shown with Show) are automatically disposed for you, since you have no control over when it will be closed by the user. No need to explicitly call Dispose!

每次创建UI对象时,Winforms都会在内部调用CreateWindow.这就是句柄的分配方式.并且只有在相应调用DestroyWindow之前,它们才被释放.在Winforms中,该调用是通过任何System.Windows.Forms.ControlDispose方法触发的. (注意:虽然我对此有一定的把握,但实际上我在猜测一点.我可能不是100%正确.使用Reflector查看Winforms内部结构会揭示真相.)

Everytime you create a UI object, Winforms internally makes calls to CreateWindow. That's how handles are allocated. And they're not freed until a corresponding call to DestroyWindow is made. In Winforms, that call is triggered through the Dispose method of any System.Windows.Forms.Control. (Note: While I'm farily certain about this, I'm actually guessing a little. I may not be 100% correct. Having a look at Winforms internals using Reflector would reveal the truth.)

假设您的StrategyEditor创建了大量的UI控件,我认为您不能做很多事情.如果您不能简化该控件(就其创建的子控件的数量而言),那么您似乎就陷入了困境.您不能创建无限多个UI控件.

Assuming that your StrategyEditor creates a massive bunch of UI controls, I don't think you can do a lot. If you can't simplify that control (with respect to the number of child controls it creates), then it seems you're stuck in the situation where you are. You simply can't create infinitely many UI controls.

但是,您可以随时跟踪打开了多少StrategyEditor个(在实例化一个计数器时增加一个计数器,而在一个实例被关闭时减少一个计数器)–您可以使用/FormClosed事件的形式,或在控件的Dispose方法中).然后,您可以将同时打开的StrategyEditor的数量限制为一个固定的数量,例如5.如果超出该限制,则可以在构造函数中引发异常,以便不再创建更多实例.当然我不能说StrategyForm是否能够很好地处理StrategyEditor构造函数中的异常...

You could, however, keep track of how many StrategyEditors are opened at any one time (increase a counter whenever one is instantiated, and decrease it whenever one is closed -- you can track the latter using the FormClosing/FormClosed event of a form, or in the Dispose method of a control). Then you could limit the number of simultaneously opened StrategyEditors to a fixed number, say 5. If the limit is exceeded, you could throw an exception in the constructor, so that no more instances are created. Of course I can't say whether StrategyForm is going to handle an exception from your StrategyEditor constructor well...

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

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

在任何一种情况下,限制实例化StrategyEditor的数量似乎对我来说都是一个临时解决办法,无法解决真正的问题.

In either case, limiting the number of instantiated StrategyEditors seems like a temporary fix to me and won't solve the real problem.

这篇关于没有足够的内存或没有足够的句柄?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆