4

次のような状況の場合:

  1. Execute()は新しいスレッドを作成し、その中で関数GetSession()を実行します。
  2. Execute()は、独自のスレッドでGetSession()を再度実行します。
  3. Execute()は、(1)のスレッドに参加します。

私の質問は:

Execute()が実行されているスレッドが現在GetSession()自体を実行しているときに、GetSession()が(1)で生成されたスレッドから例外をスローした場合はどうなりますか?

余分なスレッドから再スローされた例外は、Execute()まで伝播し、別のスレッドからのものであっても、ハンドラーに移動しますか?


この問題を示すためのサンプルコードを次に示します。

ここのウィンドウでこれを作成しました(これはモックアップです)ので、構文エラーについてお詫びします。

public void Execute()
{
    //Some logon data for two servers.
    string server1 = "x", server2 = "y", logon = "logon", password = "password";

    //Varialbes to store sessions in.
    MySession session1, session2;

    try
    {
        //Start first session request in new thread.
        Thread thread = new Thread(() =>
            session1 = GetSession(server1, logon, password));
        thread.Start();

        //Start second request in current thread, wait for first to complete.
        session2 = GetSession(server2, logon, password));
        thread.Join();
    }
    catch(Exception ex)
    {
        //Will this get hit if thread1 throws an exception?
        MessageBox.Show(ex.ToString());
        return;
    }
}

private MySession GetSession(string server, string logon, string password)
{
    try
    {
        return new MySession(server, logon, password);
    }
    catch(Exception Ex)
    {
        throw(Ex);
    }
}
4

1 に答える 1

5

Execute()が実行されているスレッドが現在GetSession()自体を実行しているときに、GetSession()が(1)で生成されたスレッドから例外をスローした場合はどうなりますか?

The threaded version will raise an unhandled exception, which will trigger AppDomain.UnhandledException. Unless this is explicitly handled there, it will tear down the application.

Does the exception re-thrown from the extra thread propagate up to Execute() and cause it to go to its handler even though it's from a different thread?

No. It will be unhandled.


Note that this is one of the advantages of the TPL. If you use Task instead of a Thread, you can make this propogate the exception back to the main thread:

try
{
    //Start first session request in new thread.
    Task<Session> task = Task.Factory.StartNew(() => GetSession(server1, logon, password));

    //Start second request in current thread, wait for first to complete.
    session2 = GetSession(server2, logon, password));
    session1 = task.Result; // This blocks, and will raise an exception here, on this thread
}
catch(Exception ex)
{
    // Now this will get hit
    MessageBox.Show(ex.ToString());
    return;
}

Note, however, that this will be an AggregateException, and requires special handling.

于 2012-07-18T15:55:35.623 に答える