Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
        }
       });
like image 485
pixel Avatar asked Jul 05 '16 19:07

pixel


People also ask

How do you handle multiple exceptions in a task?

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.

What is exception handling in Task Parallel Library?

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.

What happens if I Don't Wait on a task that propagates exceptions?

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.

How to throw an exception when a task faults?

If a task faults, the following expressions throw the exception: 1 await task 2 task.Wait () 3 task.Result 4 task.GetAwaiter ().GetResult () More ...


2 Answers

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);
like image 129
Avner Shahar-Kashtan Avatar answered Oct 13 '22 21:10

Avner Shahar-Kashtan


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.

like image 20
HaveSpacesuit Avatar answered Oct 13 '22 21:10

HaveSpacesuit