Reputation: 10547
When working with Tasks, I am not sure how to do handling when I do not call Wait on my task. The example below is not executed in an async method.
Here is an example:
var t = Task.Run(() =>
{
// do something as part of the task concurrently
});
Would wrapping the entire block above and catching Exception be correct way?
I know I can Wait for the task result like below and handle exception but my question is related to above block without call to t.Wait.
try
{
t.Wait();
}
catch(AggregateException ae)
{
// handle exception(s)
}
So, my question is whether this is correct way to handle exception when I don't Wait (or await) for task?
try
{
var t = Task.Run(() =>
{
// do something as part of the task concurrently
});
}
catch(Exception ex) //NOTE general Exception
{
// show exception in message box or log it somewhere
}
UPDATE1 , or should I do it like this?
var t = Task.Run(
() =>
{
try
{
// do something as part of the task concurrently
}
catch(Exception ex) //NOTE general Exception
{
// show exception in message box or log it somewhere
}
});
Upvotes: 15
Views: 10474
Reputation: 14700
The code you've supplied (after the edit) won't help you in handling errors thrown inside your task. It will only catch exceptions thrown in the main code block, such as in scheduling the task or getting the parameters to pass to it.
If you're using C# 5 and above (bundled with VS2013), the simplest way is to use async/await
, which simplifies control flow for asynchronous tasks:
public async Task DoSomething()
{
try
{
DoSyncWork();
await Task.Run(() => AsyncStuff());
}
catch (Exception ex)
{
// handle.
}
}
The compiler will automatically deconstruct the async task and return the exception to the normal catch
block - regardless of whether the synchronous or async parts of the code threw the exception.
If you're not using C# 5, or prefer not to use async/await (because you're handling parallelism, not just asynchrony), the technique is to use Task.ContinueWith
to specify a continuation in case of error:
var task = Task.Run(() => Whatever())
.ContinueWith(failedTask => HandleError(failedTask),
TaskContinuationOptions.OnlyOnFaulted);
This will cause the continuation to launch after the original task completes, but only if it threw an exception. You can use this to specify several continuation branches based on the result:
var baseTask = Task.Run(() => Whatever());
baseTask.ContinueWith(failedTask => HandleError(failedTask),
TaskContinuationOptions.OnlyOnFaulted);
baseTask.ContinueWith(successfulTask => HandleResults(successfulTask),
TaskContinuationOptions.OnlyOnRanToCompletion);
Upvotes: 20
Reputation: 3994
Running a task inside a try/catch block will never catch exceptions if it is not awaited. The task starts on its own thread separate from the try/catch logic, so the calling part of the program continues unless it is instructed to wait for the task to finish.
If you want it to log or handle errors, build that logic into the task itself.
Upvotes: 3