2

winフォームアプリケーションの実行時にクロススレッド例外が発生する可能性はランダムにあるようです. これが私がそれを管理しようとしている方法です:

private void ToOutput(string s)
{
    if (!this.IsHandleCreated)
        this.CreateHandle();

    if (FormOutputArea.InvokeRequired)
    {
        FormOutputArea.Invoke(new Action(delegate ()
        {
            FormOutputArea.AppendText(s + Environment.NewLine);
        }));
    }
    else
    {
        FormOutputArea.AppendText(s + Environment.NewLine);
    }
}

InvokeRequired必ずしも正確ではないようです。BeginInvoke私は同じ結果で試しました。

編集:ブレークポイントをチェックIsHandleCreatedInvokeRequiredて使用しても、それらはtrueに設定されていますelseが、条件の分岐は実行されます。

例外がスローされた場所を示すスクリーンショットを次に示します。

ここに画像の説明を入力

4

1 に答える 1

5

CreateHandle() と InvokeRequired を同じメソッドに入れるのは根本的に間違っています。これは、ハンドルがまだ作成されていないときに爆発し、間違ったスレッドでネイティブ ウィンドウを作成します。子コントロールのウィンドウは、フォームを所有するスレッドと同じスレッドによって所有されている必要があり、そのスレッドはメッセージ ループ (Application.Run) をポンプする必要があります。

簡単な回避策は、フォームのウィンドウが作成されるまでスレッドが開始されないようにすることです。これにより、そのフォームに埋め込まれたすべてのコントロールのウィンドウも作成されます。最も早く発生するのは、フォームの Load イベントです。その時点で、InvokeRequired が正確であると信頼できます。

また、ユーザーがフォームを閉じたときの問題に注意してください。スレッドの実行を継続できるようにすると、元のコードの動作が非常に悪くなります。フォームのウィンドウが作成される前にコードを爆破したのか、フォームを閉じた後に爆撃したのかはまだ明らかではありません。スレッドが停止しているか、ToOutput() を呼び出すことができなくなっていることを確認する必要があります。この回答の主題。

于 2013-09-14T15:10:42.670 に答える