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
}
});
Exceptions are propagated when you use one of the static or instance Task.Wait methods, and you handle them by enclosing the call in a try/catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.
Exception handling (Task Parallel Library) Unhandled exceptions that are thrown by user code that is running inside a task are propagated back to the calling thread, except in certain scenarios that are described later in this topic.
If you do not wait on a task that propagates an exception, or access its Exception property, the exception is escalated according to the .NET exception policy when the task is garbage-collected.
If a task faults, the following expressions throw the exception: 1 await task 2 task.Wait () 3 task.Result 4 task.GetAwaiter ().GetResult () More ...
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With