1

これを行う必要がありますか?

int x = 0;
Task<int> calc = Task.Factory.StartNew (() => 7 / x);
try
{
  Console.WriteLine (calc.Result);
}
catch (AggregateException aex)
{
  Console.Write (aex.InnerException.Message);  // Attempted to divide by 0
}

それともこれ?

int x = 0;
try
{
  Task<int> calc = Task.Factory.StartNew (() => 7 / x);
  Console.WriteLine (calc.Result);
}
catch (AggregateException aex)
{
  Console.Write (aex.InnerException.Message);  // Attempted to divide by 0
}

タスクがすぐに開始され、try catch ブロックに入る前に、それをキャッチしません...!?

4

4 に答える 4

1

Taskそういったことをほとんど気にしなくていいのも利用上のポイントの一つです。

お気づきのように、最初のサンプルには 2 つのイベント順序が考えられます。

  1. StartNew()スレッド A から呼び出されます。
  2. Resultgetter はスレッド A から呼び出されます。タスクはまだ終了していないため、呼び出しはブロックされます。
  3. デリゲートは ThreadPool スレッド B で実行され、 をスローしDivideByZeroExceptionます。
  4. スレッド A が起動し、 をResultスローしAggregateExceptionます。

2 番目の可能性は次のとおりです。

  1. StartNew()スレッド A から呼び出されます。
  2. デリゲートは ThreadPool スレッド B で実行され、 をスローしDivideByZeroExceptionます。
  3. Resultgetter はスレッド A から呼び出されます。タスクは既に終了しているため、呼び出しはすぐに をスローしAggregateExceptionます。

ご覧のとおり、どちらの場合もResultゲッターは例外をスローします。コードがどの順序で実行されたかは問題ではありません。

2番目のバージョンは、StartNew()をスローできる場合にのみ意味AggregateExceptionがありますが、それは決して起こりません。

繰り返しますが、TPL がすべての同期を処理します。ここでは気にする必要はありません。

于 2012-08-16T16:23:39.147 に答える
0

タスクにはException、タスクの実行中にスローされた例外があれば、その例外を保持するプロパティがあります。これは、次のことができることを意味します。

int x = 0;
Task<int> calc = Task.Factory.StartNew(() => 7 / x);
calc.ContinueWith(t => Console.WriteLine ("Got exception of {0}", t.Exception),
                  TaskContinuationOptions.OnlyOnFaulted);
于 2012-08-16T16:24:24.033 に答える
0

try ブロックで実行するコードはできるだけ少なくする必要があります。これは、含めれば含めるほど、スプリアスで不要な例外がキャッチされるためです。良性であることがわかっているものだけを捕まえたいのです。虫を飲み込みたくありません。

したがって、次のいずれかを行います。

var task = ...;
int result;
try { result = task.Result; } //just catch task.Result
...

またはこれさえ:

if (task.Exception != null) { /* error */ }
else { /* use task.Result */ }
于 2012-08-16T16:25:43.403 に答える
0

この場合、try ブロックに含める必要はありません。Task.Factory.StartNewは、実行する null Action を渡さない限り、例外をスローしません。実行中のアクションによってスローされた例外は、スタックではなくタスクに伝播されます。

より一般的に言えば、これらのタイプの状況の経験則は、例外は常にタスクに入るべきだということだと思います。たとえば、async メソッドで最初の await の前に例外をスローすると、スタックを伝搬する代わりに、結果のタスクにも例外が入ります。

于 2012-08-16T16:37:39.013 に答える