【问题标题】:How do you obtain Current Window Handle Count and Window Handle Limit in .NET?如何在 .NET 中获取当前窗口句柄计数和窗口句柄限制?
【发布时间】:2010-09-13 16:19:18
【问题描述】:

我想在 C# 中获取当前窗口句柄数和系统范围的窗口句柄限制。我该怎么办?

【问题讨论】:

    标签: .net window handle


    【解决方案1】:

    正如 Raymond Chen 前段时间所说,如果您正在考虑窗口句柄限制,那么您可能做错了什么:)

    无论如何,我敢打赌没有特殊的 C# 方法可以做到这一点,因为它是系统特定的。您可以使用在 C++ 应用程序中使用的相同函数。使用 P/Invoke 调用函数。要了解如何编写导入,请转至 pinvoke.net

    编辑:据我了解您的问题,我假设您已经知道如何在 Win32 应用程序中执行此操作。

    【讨论】:

      【解决方案2】:

      OregonGhost 引用的完整引用是

      如果你不得不问,你可能做错了什么。

      来自Why is the limit of window handles per process 10,000? 你应该看看这个。

      【讨论】:

        【解决方案3】:

        如果您阅读 Raymond Chen 的帖子,您可能会发现它和我一样烦人。您只是“可能做错了什么”,因为您正在做 Windows 无法做到的事情。

        在我的应用程序中,当用户第一次访问标签页时,我会创建并布置该页上的所有控件。这需要相当长的时间——一个页面上很容易有 50 个控件。因此,如果可能的话,我不会在填充标签页后丢弃它,并将关闭的标签页集留给用户。

        碰巧的是,有些用户从不想关闭任何组标签页。我为什么要强迫他们?使用我的 UI,他们可以非常快速地导航到他们负责管理的 300 多组交易中的任何一组。他们的机器足够快,并且有足够的内存,使这一切都非常敏感。唯一的问题是 Windows 不支持。

        为什么我使用控件,而不是其他一些 UI 技术?因为他们工作。我需要支持焦点事件、选项卡顺序、验证事件、动态布局和数据绑定——用户实际上是在内存数据集中管理数十个表中的数千条记录。我必须做的开发量 - 比如说 - 使用无窗口控件实现某些东西是天文数字。

        我只是“做错了”,因为 Windows 对它可以支持的窗口句柄数量有硬性限制。这个硬限制是基于一堆关于如何构建计算机 UI 的十年前的假设。 “做错事”的不是我。

        无论如何,我对此的解决方案分为两部分。

        首先,一个类可以告诉您您的进程正在使用多少个窗口句柄:

        using System;
        using System.Runtime.InteropServices;
        
        namespace StreamWrite.Proceedings.Client
        {
            public class HWndCounter
            {
                [DllImport("kernel32.dll")]
                private static extern IntPtr GetCurrentProcess();
        
                [DllImport("user32.dll")]
                private static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags);
        
                private enum ResourceType
                {
                    Gdi = 0,
                    User = 1
                }
        
                public static int GetWindowHandlesForCurrentProcess(IntPtr hWnd)
                {
                    IntPtr processHandle = GetCurrentProcess();
                    uint gdiObjects = GetGuiResources(processHandle, (uint)ResourceType.Gdi);
                    uint userObjects = GetGuiResources(processHandle, (uint)ResourceType.User);
        
                    return Convert.ToInt32(gdiObjects + userObjects);
                }
            }
        }
        

        其次,我维护一个最近最少使用的标签页对象缓存。 .NET 框架没有提供通用的 LRU 缓存类,所以我构建了一个,如果需要,可以获取 here。每次用户访问标签页时,我都会将其添加到 LRU 缓存中。然后我检查我是否在窗口句柄上运行不足。如果是,我会丢弃最近最少使用的标签页上的控件,并继续这样做,直到我再次拥有足够的窗口句柄。

        【讨论】:

        • 感谢您的代码。当我达到 10000 个句柄时,我的应用程序不会崩溃,那么我怎么知道我离限制有多近?另一方面,我在任务管理器中遇到“创建窗口句柄时出错”崩溃,句柄计数低至几百个,所以这些崩溃可能与限制无关。我同意陈先生的 cmets 很烦人,尤其是当我在任务管理器中查看句柄数时,发现在 4000-6000 句柄范围内的两个应用程序是 devenv.exe 和 Outlook.exe!所以不要告诉我我做错了什么,“MSFT”先生!
        猜你喜欢
        • 1970-01-01
        • 2015-02-23
        • 1970-01-01
        • 1970-01-01
        • 2012-11-22
        • 1970-01-01
        • 2011-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多