DOBON.NET DOBON.NETプログラミング掲示板過去ログ

マルチスレッドで例外発生時、EndInvokeでアプリが落ちる

環境/言語:[WinXP/Vista、C#(.NET2.0)]
分類:[.NET]

OS:WinXP,Vista
.NET:2.0(C#)

こんにちは
あるクラスDLL(.NET2.0/C#製)のメソッドを非同期で呼び出す処理を行っています。

以下のようにクラスインスタンスのメソッドを非同期デリゲートを使って呼びだしています。
SampleDelegate sampleDlgt = new SampleDelegate(smpl.TestRun);
sampleDlgt.BeginInvoke(param, new AsyncCallback(CallbackMethod), sampleDlgt);

またコールバックメソッドではEndInvokeを行うためのコードがあります。
private static void CallbackMethod(IAsyncResult ar)
{
    SampleDelegate dlgt = ar.AsyncState as SampleDelegate;

    if (dlgt != null)
    {
        dlgt.EndInvoke(ar);
    }
}


ここで、非同期で呼び出した処理内で例外が発生した時、
すぐにコールバックメソッドが呼ばれるのですが、そのEndInvokeで
メインスレッドとなっているアプリ自体が強制終了されてしまいます。

とりあえずスレッド側の例外をキャッチする方法を調べていますが、
それとEndInvokeでアプリ自体が落ちてしまうこととの関連性が
見つからないため行き詰っています…

何卒ご教示いただければ幸いです。

以上よろしくお願いします
2011/08/12(Fri) 15:29:40 編集(投稿者)

■No28872に返信(ぺんたごんさんの記事)
> ここで、非同期で呼び出した処理内で例外が発生した時、
> すぐにコールバックメソッドが呼ばれるのですが、そのEndInvokeで
> メインスレッドとなっているアプリ自体が強制終了されてしまいます。

EndInvoke の呼び出しによって、その別スレッドで起きていた例外がそのスレッドでスローされ直しているだけでは?
その例外をハンドルしていないが故に、アプリケーションが落ちているのではないでしょうか?

試しに、try { dlg.EndInvoke(ar); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } などと書いてみて、Exception の情報を見てみては?

なお、コールバックはメインスレッドで実行されるわけではありません。
ご注意ください。
デバッグで中断して、スレッドの一覧を確認するとわかると思います。
返信ありがとうございます。
別スレッド実行しているメソッド内で発生したイベントも
別スレッドである、というのは知っていましたがコールバックもだとは
知りませんでした。

ただ気になっているのはEndInvokeした瞬間に
「メインスレッドで例外が発生する、それをVisualStudioがハンドルされてないと通告する」
のならAzuleanさんのおっしゃる原因でビンゴだと思うのですが
「無言でプロセスが落ちる、VisualStudioも無言でデバッグを終了する」
のであるぇー?となっていたのです。

とりあえず試しにtry-catchで囲ってみます(来週明けになりますが…)

■No28876に返信(Azuleanさんの記事)
> 2011/08/12(Fri) 15:29:40 編集(投稿者)
> EndInvoke の呼び出しによって、その別スレッドで起きていた例外がそのスレッドでスローされ直しているだけでは?
> その例外をハンドルしていないが故に、アプリケーションが落ちているのではないでしょうか?
>
> 試しに、try { dlg.EndInvoke(ar); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } などと書いてみて、Exception の情報を見てみては?
>
> なお、コールバックはメインスレッドで実行されるわけではありません。
> ご注意ください。
> デバッグで中断して、スレッドの一覧を確認するとわかると思います。
2011/08/13(Sat) 21:19:37 編集(投稿者)

■No28881に返信(ぺんたごんさんの記事)
> ただ気になっているのはEndInvokeした瞬間に
> 「メインスレッドで例外が発生する、それをVisualStudioがハンドルされてないと通告する」
> のならAzuleanさんのおっしゃる原因でビンゴだと思うのですが

そもそも、メインスレッドで例外はでません。
コールバックメソッドが実行されているスレッド(メインスレッドではないはず)で例外が発生しているので、ハンドルされていないと通告するわけです。

> 「無言でプロセスが落ちる、VisualStudioも無言でデバッグを終了する」

デバッグなしで実行していれば、無言で落ちる可能性はあります。
Windows のバージョンや設定によっては、「ご迷惑をおかけしました」とでて報告する・しないのダイアログになるかと思われます。
(例外発生時のスタックトレースが見えるあのダイアログはメインスレッドのメッセージループ内で例外が発生した場合のみであり、ワーカースレッドで発生した例外は対象外となる)

Visual Studio も無言でデバッグ終了するケースはどういった場合が考えられるかなぁ。
とりあえず、上述のサンプルコードをベースとした手元の実験では VS2010 でまずデリゲート内でハンドルされていない例外として止まり、その状態で F5 キーでさらに進めると、EndInvoke でハンドルされていない例外として止まりました。

DOBON.NET | プログラミング道 | プログラミング掲示板