Delay then execute Task
Quick question, I want to wait a second before launching an async task without a return value.
Is this the right way to do it?
Task.Delay(1000)
.ContinueWith(t => _mq.Send(message))
.Start();
What happens to exceptions?
Solution 1:
First of all, Start()
only works on the (very rare) Task
s that were created using the Task
constructor (e.g. new Task(() => _mq.Send(message))
). In all other cases, it will throw an exception, because the Task
is already started or waiting for another Task
.
Now, probably the best way to do this would be to put the code into a separate async
method and use await
:
async Task SendWithDelay(Message message)
{
await Task.Delay(1000);
_mq.Send(message);
}
If you do this, any exception from the Send()
method will end up in the returned Task
.
If you don't want to do that, using ContinueWith()
is a reasonable approach. In that case, exception would be in the Task
returned from ContinueWith()
.
Also, depending on the type of _mq
, consider using SendAsync()
, if something like that is available.
Solution 2:
You can catch any exception thrown in the Task if you Wait for the Task to finish:
Be aware of that your Exception thrown in the Task is going to be the inner one
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");
}
}