2

次の構造の匿名 TPL タスクがあります。

   Task.Factory.StartNew(() =>
        {
            try
            {
                DoStuff();
            }
            catch (OperationCanceledException ex)
            {
                // process cancellation
            }
            catch (Exception ex)
            {
                // process (log) all exceptions
            }
            finally
            {
                // tie up various loose ends
            }
        },
            myCancellationToken, // cancellation token
            TaskCreationOptions.LongRunning, // always create a new thread
            TaskScheduler.Default // default task scheduler
        );

DoStuff () 関数内では、Dropbox 用の Spring.NET Social 拡張機能を使用して、大きなファイルを Dropbox にアップロードしています。まだ理解していない何らかの理由で、ファイルのアップロード中に ( UploadFileAsync() メソッド呼び出しを介して) 例外が生成されています。

(System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine).

なぜこの例外が発生するのかはまだ調査中ですが、それは私がプレゼントに関係する部分ではありません. より大きな問題は、例外が最終的に System.Reflection.TargetInvocationException によってラップされ、何らかの奇妙な理由で、(元のコード スニペットの) try/catch ブロックがそれをキャッチしていないことです。

例外をキャッチできないため、最終的にアプリがクラッシュします。

必要だとは思いませんでしたが、TargetInvocationException の明示的な catch ブロックを追加しようとさえしましたが、やはり起動しません。

私の質問は、この例外をどのようにキャッチするのですか?上記のコードに示されている構成によってキャッチされないのはなぜですか?

アップデート:

結局、この問題は TPL とは何の関係もないようです。コードが同期的に実行されるように StartNew() の呼び出しを削除するように呼び出しを変更しましたが、まだこの例外をキャッチできません。

4

1 に答える 1

1

このコードを使用して、TargetInvocationException をキャッチできることを確認しました。

[Test]
public void TaskExceptionTest()
{

    var task = Task.Factory.StartNew(
        () =>
        {
            try
            {
                throw new TargetInvocationException(null);
            }
            catch (Exception e)
            {
                Console.WriteLine("Caught one (inside):" + e.GetType().Name);
            }
        });
    try
    {
        task.Wait();
    }
    catch (AggregateException ae)
    {
        // Assume we know what's going on with this particular exception. 
        // Rethrow anything else. AggregateException.Handle provides 
        // another way to express this. See later example. 
        foreach (var e in ae.InnerExceptions)
        {
            if (e is TargetInvocationException)
            {
                Console.WriteLine("After:" + e.GetType().Name);
            }
            else
            {
                throw;
            }
        }
    }
}

例外処理とタスクについては、こちらを参照してください。

于 2012-11-12T18:30:40.003 に答える