如何在.NET中获取当前窗口句柄计数和窗口句柄限制?

时间:2008-09-27 08:03:05

标签: .net window handle

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

3 个答案:

答案 0 :(得分:16)

如果您阅读Raymond Chen的帖子,您可能会觉得它像我一样烦人。你只是“可能做错了”,因为你正在做一些Windows无法做到的事情。

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

实际上,有些用户从不想关闭任何标签页。我为什么要强迫他们去?通过我的用户界面,他们可以快速导航到他们负责管理的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缓存中。然后我检查我是否在窗户把手上跑得很低。如果是的话,我会丢弃最近最少使用的标签页上的控件,并继续这样做,直到我再次有足够的窗口句柄。

答案 1 :(得分:3)

正如Raymond Chen不久前提出的那样,如果你正在考虑窗口句柄限制,你可能做错了什么:)

无论如何,我打赌没有特别的C#方式来做,因为它是非常特定于系统的。您可以使用在C ++应用程序中使用的相同功能。使用P / Invoke调用函数。要了解如何编写导入,请转到pinvoke.net

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

答案 2 :(得分:0)

OregonGhost引用的完整报价是

  

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

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