21

私は以下を使用しています

Task.Factory.StartNew(() => DoPrintConfigPage(serial));

次に、私が呼び出している関数は次のようになります

private void DoPrintConfigPage(string serial) 
{ 
    //do printing work 
}

私の問題は、例外がスレッド内にスローされ、処理されないことです。

トライキャッチで包んでみました

try
{
    Task.Factory.StartNew(() => DoPrintConfigPage(serial));
}
catch (Exception ex) { }

しかし、それでもエラーをキャッチしていないため、アプリケーションがクラッシュします。

メインスレッドで例外をキャッチして処理できるようにするにはどうすればよいですか?

アップデート

以下に推奨する変更を加えましたが、それでも例外は処理されないと言っています

var task =  Task.Factory.StartNew(() => DoPrintConfigPage(serial))
                               .ContinueWith(tsk =>
                               {
                                  MessageBox.Show("something broke");
                               },TaskContinuationOptions.OnlyOnFaulted);

それから私のDoConfigPage中に別のトライキャッチを追加しました。

このキャッチでは、クラッシュし、スローされた例外が処理されなかったと言っていますが、何が欠けていますか?

private void DoPrintConfigPage(string serial)
{
    try
    {
        //call the print function
    }
    catch (Exception ex)
    {
        throw ex;   //it is crashing here and saying it is unhandled
    }
}

エリックJ.が提案したものも試してみましたが、同じ結果になりました

var task = Task.Factory.StartNew(() => DoPrintConfigPage(serial));

try
{
    task.Wait();                  
}
catch (AggregateException ex) { MessageBox.Show("something broke"); }
4

5 に答える 5

40

または、タスクの作成を連鎖させて、ContinueWith を追加することもできます。

var job = Task.Factory
    .StartNew(...)
    .ContinueWith(tsk => 
         {
              // check tsk for exception and handle
         });

編集: このスニペットを実行すると、メッセージ ボックスがポップアップ表示されます。

void Main()
{
    var serial = "some serial";
    var task =  Task.Factory
        .StartNew(() => DoPrintConfigPage(serial))
        .ContinueWith(tsk =>
        {
            MessageBox.Show("something broke");
            var flattened = tsk.Exception.Flatten();

            // NOTE: Don't actually handle exceptions this way, m'kay?
            flattened.Handle(ex => { MessageBox.Show("Error:" + ex.Message); return true;});
        },TaskContinuationOptions.OnlyOnFaulted);

}

public void DoPrintConfigPage(string serial)
{
    throw new Exception("BOOM!");
}
于 2013-02-14T21:01:55.447 に答える
11

新しいタスクtryを開始した直後にブロックが終了します。これは、そのメソッドが引き続き実行されるためです。

代わりに、タスク(または複数のタスク)が完了するのを待つAggregateExceptionとして例外をキャッチできます。

var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("I'm bad, but not too bad!");
});

try
{
    task1.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 MyCustomException)
        {
            Console.WriteLine(e.Message);
        }
        else
        {
            throw;
        }
    }

}

http://msdn.microsoft.com/en-us/library/dd997415.aspx

于 2013-02-14T20:56:04.067 に答える
7

タスクを待っていない場合、最も簡単な解決策はTask.Exceptionにあると思います:

Task が途中で終了する原因となった AggregateException を取得します。タスクが正常に完了したか、まだ例外をスローしていない場合、これは null を返します。

私はこのようなものを使用しています:

Task.Factory.StartNew(() => DoStuffHere())
    .ContinueWith(task =>
    {
        if (task.Exception != null)
            Log("log all the exceptions!");
    });
于 2015-08-27T16:31:24.503 に答える
3

System.Threading.Tasks.TaskScheduler.UnobservedTaskExceptionについても知っておく必要があり ます。

「ファイア アンド フォーゲット」Taskインスタンスを作成している場合は、プログラムの開始時にそのイベントをサブスクライブする必要があります。

于 2013-02-14T21:01:25.237 に答える