WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

不正なクロススレッドコールの捕捉

by WebSurfer 11. July 2019 16:43

Windows Forms のマルチスレッドアプリで不正なクロススレッドコールがある場合、Visual Studio から[デバッグの開始(S)]でなら以下のような例外が捕捉されるが、[デバッグなしで開始(H)]では捕捉されないという話を書きます。

不正なクロススレッドコールの捕捉

元の話は Teratail の「非同期処理でデバッグ時・ビルド実行時で処理結果が異なる?」というスレッドから来ています。

例えば、Windows Forms アプリの Button.Click のイベントハンドラで、以下のように AsParallel 拡張メソッドを使ってマルチスレッドで処理するケースを考えます。

private void button4_Click(object sender, EventArgs e)
{
    Enumerable.Range(1, 10).AsParallel().ForAll(z =>
    {
        this.textBox2.Text += z.ToString();
    });
}

this.textBox2.Text += z.ToString(); の行で、textBox2 が作成された UI スレッドとは別のスレッドから textBox2 の呼び出しを行っています。これが不正なクロススレッドコールになります。

このコードを Visual Studio から[デバッグの開始(S)]で実行した場合は、デバッガがこの行で InvalidOperationException 例外をスローし、"コントロールが作成されたスレッド以外のスレッドからコントロール 'textBox2' がアクセスされました" というエラーメッセージを表示します。それが上の画像です。

ところが[デバッグなしで開始(H)]で実行した場合は例外はスローされず、あたかもこのコードは正常終了したかのように見えます。集約的例外ハンドラで捕捉してアプリケーションを終了させるということもできません(そもそも例外がスローされないので)。

という訳で、特にマルチスレッドアプリを開発している場合は必ず[デバッグの開始(S)]で実行して動作確認をするようにした方がよさそうです。

なお、[デバッグなしで開始(H)]でも CheckForIllegalCrossThreadCalls プロパティを true(デフォルトは false)に設定すれば不正なクロススレッドコールで例外をスローさせることはできます。

でも、たぶんオーバーヘッドが増えてパフォーマンスに影響があるでしょうからリリース前には元に戻さなければならず、そんな面倒なことをするより[デバッグの開始(S)]で実行して確認するのが正解だと思います。

Tags:

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  July 2019  >>
MoTuWeThFrSaSu
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar