まず第一に、私の母国語ではないので、私の英語は申し訳ありません。
.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)に達したときに発生します。
専門家の意見を聞かせてください。よろしくお願いします。