pixel
pixel

Reputation: 10547

Task Exception Handling without Wait

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

Answers (2)

Avner Shahar-Kashtan
Avner Shahar-Kashtan

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.

Async/Await to simplify asynchronous task control flow

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.

OnlyOnFaulted continuations to handle task exceptions

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

HaveSpacesuit
HaveSpacesuit

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

Related Questions