1. ホーム
  2. c#

Task.Runの例外処理方法

2023-09-01 13:04:01

質問

からの例外をキャッチするのに問題がありました。 Task.Run を以下のように変更することで解決しました。この2つの方法で例外を処理することの違いを知りたいのですが.

Outside メソッドでは例外をキャッチできませんが Inside メソッドではできます。

void Outside()
{
    try
    {
        Task.Run(() =>
        {
            int z = 0;
            int x = 1 / z;
        });
    }
    catch (Exception exception)
    {
        MessageBox.Show("Outside : " + exception.Message);
    }
}

void Inside()
{
    Task.Run(() =>
    {
        try
        {
            int z = 0;
            int x = 1 / z;
        }
        catch (Exception exception)
        {
            MessageBox.Show("Inside : "+exception.Message);
        }
    });
}

どのように解決するのですか?

タスクが実行されると、そのタスクが投げる例外は保持され、何かがタスクの結果を待つときやタスクが完了するときに再度スローされます。

Task.Run()Task オブジェクトを返します。

var task = Task.Run(...)

try
{
    task.Wait(); // Rethrows any exception(s).
    ...

新しいバージョンの C# では await の代わりにTask.Wait()を使うことができます。

try
{
    await Task.Run(...);
    ...

の方がずっとすっきりしていますね。


完全なものにするために、コンパイル可能なコンソールアプリケーションを以下に示します。 await :

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            test().Wait();
        }

        static async Task test()
        {
            try
            {
                await Task.Run(() => throwsExceptionAfterOneSecond());
            }

            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        static void throwsExceptionAfterOneSecond()
        {
            Thread.Sleep(1000); // Sleep is for illustration only. 
            throw new InvalidOperationException("Ooops");
        }
    }
}