web-dev-qa-db-ja.com

遅延してからタスクを実行

簡単な質問、私はwait起動前非同期タスク戻り値なしにしたいです。
これは正しい方法ですか?

Task.Delay(1000)
    .ContinueWith(t => _mq.Send(message))
    .Start();

例外はどうなりますか?

40
David

まず、Start()は、Taskコンストラクターを使用して作成された(非常にまれな)Tasks(たとえば、new Task(() => _mq.Send(message)))でのみ機能します。それ以外の場合は、Taskがすでに開始されているか、別のTaskを待機しているため、例外がスローされます。

さて、おそらくこれを行う最良の方法は、コードを別のasyncメソッドに入れてawaitを使用することです。

_async Task SendWithDelay(Message message)
{
    await Task.Delay(1000);
    _mq.Send(message);
}
_

これを行うと、Send()メソッドの例外が返されたTaskになります。

そうしたくない場合は、ContinueWith()を使用するのが合理的なアプローチです。その場合、例外はContinueWith()から返されるTaskにあります。

また、__mq_のタイプに応じて、SendAsync()の使用を検討してください(そのようなものが利用可能な場合)。

38
svick

タスクが完了するのを待つと、タスクでスローされた例外をキャッチできます。

タスクでスローされた例外が内部のものになることに注意してください

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Task task = Task.Delay(1000)
                .ContinueWith(t => Program.throwsException());

            task.Wait();     
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception:" + ex.Message); // Outputs: Exception:One or more errors occurred.
            Console.WriteLine("Inner exception:" + ex.InnerException.Message); // Outputs: Exception:thrown
        }
        Console.ReadKey();

    }
    static void throwsException()
    {
        Console.WriteLine("Method started");
        throw new Exception("thrown");
    }
}
11
Attila

タスクをWaitすると、例外を観察できます。

タスク内で実行されているユーザーコードによってスローされた未処理の例外は、このトピックで後述する特定のシナリオを除き、結合スレッドに伝播されます。例外は、静的またはインスタンスのTask.WaitまたはTask.Waitメソッドのいずれかを使用し、try-catchステートメントで呼び出しを囲むことによって処理するときに伝播されます。

例外処理からの抜粋(タスク並列ライブラリ)

タイミングに注意してください。タスクはスケジューラを使用するため、「go」と言ったときに開始することは保証されません。コードは、Startに指示した後、少なくとも 1000msの遅延を保証しますが、1000ms exactlyである保証はありません。

0
Gusdor