5

これは、未処理の例外を通知します。

new Thread(_ => { throw new Exception(); }).Start();

これはしません(少なくとも結果を待つ/取得するまで):

Task.Factory.StartNew(() =>
        {
            throw new Exception();
        });

なんで?例外がスローされたスレッドはどうなりましたか? それは死にますか?

これは、次のように、タスクを実行するが、その結果を必要としない、または待機する必要がない場合の問題です。

_operationQueue = new BlockingCollection<Operation>();

Task.Factory.StartNew(() => 
{
     foreach (var item in _operationQueue.GetConsumingEnumerable())
     {
         // do something that throws
     }
}, TaskCreationOptions.LongRunning);

この場合、_operationQueue左側はどのような状態ですか?

TaskContinuationOptions.OnlyOnFaulted で継続を使用できることはわかっていますが、処理を再開できますか?

4

2 に答える 2

9

さて、代わりに何が起こるべきだと思いますか?別のスレッドで例外がスローされるたびに、そのタスクを開始したスレッドにすぐに伝播する必要があると考えていますか? 私は強く反対します。まず、呼び出し元のスレッドのコードが途中で操作を強制的に中止させられ、重大な問題が発生する可能性が高くなります。関連するすべての投稿を調べてThread.Abort、プログラムの実行中の特定の既知のポイントではなく、任意のポイントで例外をスローできるようにするときに発生する非常に重大な問題をすべて確認してください。

タスクのコードが例外をスローしたときにプログラム全体がクラッシュすることを提案している場合、概して、それは単に望ましくないと言えます。まれに、タスクに障害が発生した場合にプロセス全体を終了するタスクの継続を (かなり簡単に) 作成できます。ただし、そのような継続を自分で作成する必要はまだありません。タスクが例外をスローしたときにプロセスを停止するようにシステムが設計されている場合、反対の動作を取得することはそれほど簡単ではありません。

例外がスローされたスレッドはどうなりましたか? それは死にますか?

例外がキャッチされた場合、キャッチ後に実行が続行されます。呼び出しスタック全体に伝播する場合、例外は、Task例外をラップして継続で使用できるようにするフレームワーク内のコードによってキャッチされます。

この場合、_operationQueue はどの状態のままですか?

1..N 個のアイテムが削除された完全に問題のないキューです。ループの本体が常にスローされる場合、1 つのアイテムがループから取得されます。たまにしか投げられない場合は、そこからいくつかのアイテムが取られます。残りのアイテムはまだキューにあり、それにアクセスできる他のスレッドによって削除できます。キューにアクセスできなくなった場合、ガベージ コレクションの対象になります。

TaskContinuationOptions.OnlyOnFaulted で継続を使用できることはわかっていますが、処理を再開できますか?

呼び出しスレッドは次のことができます。もちろん。try/catchタスク自体は、デリゲート内にある場合にのみ続行できます。タスクに障害が発生するまで例外がスローされた場合、そのタスクの実行を続行することはできません。

于 2013-06-17T15:47:43.377 に答える
3

タスクの例外は、によってキャッチされますTaskScheduler。タスクの結果を監視したくないが、タスクで未処理の例外について通知したい場合は、TaskScheduler.UnobservedTaskExceptionイベントがあります。このイベントはすぐに発生するのでTaskはなく、例外が取得されていない場合のファイナライズ時に発生することに注意してください。.Net 4 では、監視されていないタスクの例外が再スローされ、プロセスを終了する未処理の例外になりましたが、これは .Net 4.5 で変更されました。

于 2013-06-17T15:55:09.010 に答える