1

まず第一に、私の母国語ではないので、私の英語は申し訳ありません。

.NET Windowsフォームアプリケーションで問題が発生し、何らかの理由でVirtaul PC Windows 7(x64)でのみ再現されました。

タブコントロールなどを積み重ねた2つを含む、多くのカスタムコントロールを含むメインアプリケーションフォームのサイズを変更するときに、アプリケーションの1つの場所でWin32Exceptionに直面しました...例外のメッセージは「ウィンドウハンドルの作成中にエラーが発生しました」でした。しばらく時間をかけて、Microsoftサポートサイトでその問題の解決策を見つけました。それは私の場合と非常に似ていました。サイトからのQoute:

.NETアプリケーションでは、ドッキングされたコントロールは、親が深くネストされている場合、親のサイズが変更されてもサイズが変更されないことがあります。この問題は、64ビットプラットフォームと32ビットプラットフォームの両方で発生しますが、32ビットシステムではより深いネストレベルが必要です。

何が起こるかというと、最上位のコントロールがレイアウトされると、SetBoundsCoreはSetWindowPosを呼び出して子コントロールのサイズを変更します。各子コントロールはWM_WINDOWPOSCHANGED通知を受信します。これにより、SetWindowPosを呼び出すSetBoundsCoreを呼び出すレイアウトイベントがトリガーされます。SetWindowPosを呼び出すたびにカーネルモードになり、その後バックアウトしてWM_WINDOWPOSCHANGED通知を配信します。最終的に、スレッドはカーネルスタックスペースを使い果たし、SetWindowPosはサイレントに失敗します。

提案された解決策は、コンテナコントロール(PanelsやTabControl(私の場合)など)のOnSizeChangedメソッドをオーバーライドすることです。

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

私はこのソリューションを私のケースにうまく適用しました:カスタムTabControl(プレーンなwinforms TabControlクラスから継承)を作成し、カスタムコントロールインスタンスでTabControlインスタンスを変更しました。そして問題はなくなりました!だが...

... CCnetビルドマシンでBuildを起動すると、さまざまな単体テストでWin32Exceptionの「ウィンドウハンドルの作成エラー」が発生しましたが、問題のあるコントロール(カスタムTabControlオブジェクトを含む)ユニットの代わりに最も興味深いものはありませんテスト!エラーのケースは異なりますが、カスタムコントロールとは関係ありませんでした。変更を元に戻してすべてが正常であると、ビルドが作成されました(単体テストは正常に実行されました)。

適用された変更によってユーザーアプリケーションの作業性が修正されるが、ビルドの作成時に単体テストが失敗することにつながることは、私を完全に混乱させました。

ちなみに、ローカルマシンでは、すべての単体テストはどのような場合でも問題なく実行されます(修正の有無にかかわらず)。

私はこの問題の調査に多くの時間を費やしましたが、今では1つの仮定しかありません:ccnetビルドマシンは1つのプロセスですべての単体テストを実行し、テストはエラー「エラー」のためにテストデータ(gdiオブジェクト)を正しく(分解時に)破棄しませんウィンドウハンドルの作成」は通常、許可されたgdiオブジェクトハンドルの制限(10000)に達したときに発生します。

専門家の意見を聞かせてください。よろしくお願いします。

4

3 に答える 3

0

CCNETマシンで単体テストとして実行している場合は、非対話型のサービスコンテキストで実行されている可能性があります。これにより、ウィンドウを表示するユーザーがいないため、ウィンドウを作成できなくなる可能性があります。

于 2012-05-08T15:35:25.317 に答える
0

エラーとは直接関係ありませんが、Handle プロパティにアクセスすると、ウィンドウ ハンドルが強制的に作成されますが、これは不可能な場合があります。ハンドル チェックは、次のように実行しないでください。

if (this.Handle != null)

代わりに、IsHandleCreated プロパティを確認してください。

if (this.IsHandleCreated)

しばらく前にこの問題に関するブログ投稿でこれについて言及しましたが、注目されていないようです。

于 2012-05-08T15:13:24.353 に答える
0

深くネストされたコントロールでも同じ問題がありました。ただし、適切な解決策を得るには、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);
                             });
        }
    }
于 2015-11-19T12:01:27.970 に答える