簡単な質問、私はwait秒起動前非同期タスク戻り値なしにしたいです。
これは正しい方法ですか?
Task.Delay(1000)
.ContinueWith(t => _mq.Send(message))
.Start();
例外はどうなりますか?
まず、Start()
は、Task
コンストラクターを使用して作成された(非常にまれな)Task
s(たとえば、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()
の使用を検討してください(そのようなものが利用可能な場合)。
タスクが完了するのを待つと、タスクでスローされた例外をキャッチできます。
タスクでスローされた例外が内部のものになることに注意してください
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");
}
}
タスクをWait
すると、例外を観察できます。
タスク内で実行されているユーザーコードによってスローされた未処理の例外は、このトピックで後述する特定のシナリオを除き、結合スレッドに伝播されます。例外は、静的またはインスタンスのTask.WaitまたはTask.Waitメソッドのいずれかを使用し、try-catchステートメントで呼び出しを囲むことによって処理するときに伝播されます。
タイミングに注意してください。タスクはスケジューラを使用するため、「go」と言ったときに開始することは保証されません。コードは、Start
に指示した後、少なくとも 1000msの遅延を保証しますが、1000ms exactlyである保証はありません。