Win32异常:创建窗口句柄时出错(大量嵌套控件)



首先,对不起我的英语,因为它不是我的母语。

问题发生在我的.NET Windows Forms应用程序中,并且由于某些原因仅在Virtaul PC Windows 7(x64(上重现。

在调整包含许多自定义控件的主应用程序窗体的大小时,我在应用程序的一个位置遇到了 Win32Exception,包括两个相互堆叠的选项卡控件等......异常的消息是"创建窗口句柄时出错"。花了一些时间,我在Microsoft支持网站上找到了该问题的解决方案。这与我的情况非常相似。来自网站的Qoute:

在 .NET 应用程序中,如果停靠控件是深度嵌套的,则在调整其父控件的大小时,这些控件有时不会调整大小。 此问题在 64 位和 32 位平台上都会发生,但在 32 位系统上需要更深的嵌套级别。

发生的情况是,当顶级控件布局时,SetBoundsCore 调用 SetWindowPos 来调整子控件的大小。每个子控件都接收一个WM_WINDOWPOSCHANGED通知,该通知触发布局事件,该事件调用 SetBoundsCore,该事件调用 SetWindowPos。 每次调用 SetWindowPos 都会进入内核模式,然后返回以传递WM_WINDOWPOSCHANGED通知。最终,线程耗尽内核堆栈空间,SetWindowPos 以静默方式失败。

建议的解决方案是覆盖容器控件(如面板或选项卡控件(在我的情况下((的 OnSizeChanged 方法:

    protected override void OnSizeChanged(EventArgs e)
    {
        if (this.Handle != null)
        {
            BeginInvoke((MethodInvoker)(() => base.OnSizeChanged(e);));
        }
    }

成功地将此解决方案应用于我的情况:创建自定义 TabControl(继承自普通 winforms TabControl 类(并使用我的自定义控件实例更改 TabControl 实例。问题消失了!但。。。

。当我在 CCnet 构建机器上启动构建时,我在不同的单元测试中有很多 Win32Exception-s"创建窗口句柄时出错",但最有趣的是不是代替我有问题的控件(包含自定义 TabControl 对象(单元测试!错误情况不同,但它们与我的自定义控件无关。当我恢复更改时,一切正常,构建已创建(单元测试成功执行(。

应用更改修复了用户应用程序的可操作性,但在创建构建时导致单元测试失败,这让我完全感到困惑。

顺便说一下,在本地计算机上,所有单元测试在任何情况下都正常执行(有或没有修复(。

花了很多时间调查这个问题,现在我只有一个假设:ccnet 构建机器在一个进程中执行所有单元测试,并且测试不会正确处理测试数据(gdi 对象((拆卸时(,因为错误"创建窗口句柄时出错"通常在达到允许的 gdi 对象句柄限制 (10000( 时发生。

您能分享一下您的专业意见吗?提前非常感谢。

与您的错误没有直接关系,但访问 Handle 属性将强制创建窗口句柄,这有时是不可能的。 不应像这样执行句柄检查:

if (this.Handle != null)

相反,请检查 IsHandleCreated 属性:

if (this.IsHandleCreated)

不久前,我在关于这个问题的博客文章中提到了这一点,但似乎没有被注意到。

如果在 CCNET 计算机上作为单元测试运行,则它可能在非交互式服务上下文中运行,这可能会阻止创建窗口,因为没有人可以查看它们。

我在深度嵌套控件时遇到了同样的问题。但是,为了获得适当的解决方案,我不得不覆盖并延迟SetBoundsCore

    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        if (this.IsHandleCreated)
        {
            this.BeginInvoke(
                             (MethodInvoker)delegate
                             {
                                 base.SetBoundsCore(x, y, width, height, specified);
                             });
        }
    }

最新更新