Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception handling with TPL

Using TPL/Tasks I can perform exception handling using inner try/catch statement:

  Task.Factory.StartNew(
    ()=>
      {
        try
        {
          // Do stuff
        }
        catch
        {
          // Handle exception
        }
      });

Or using ContinueWith, like so:

Task.Factory.StartNew(
    ()=>
      {
          // Do stuff
      }).ContinueWith(
        task =>
        {
          if(task.Exception != null)
            // Handle exception
        });

Which method is more recommended to use? What are the cons and pros for each?

like image 923
Eran Betzalel Avatar asked Feb 13 '13 12:02

Eran Betzalel


People also ask

How do you handle exceptions in TPL C#?

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.

How do you handle exceptions in parallel ForEach?

For and Parallel. ForEach overloads do not have any special mechanism to handle exceptions that might be thrown. In this respect, they resemble regular for and foreach loops ( For and For Each in Visual Basic); an unhandled exception causes the loop to terminate as soon as all currently running iterations finish.

What is exception handling in c3?

Exception Handling in C# is a process to handle runtime errors. We perform exception handling so that normal flow of the application can be maintained even after runtime errors. In C#, exception is an event or object which is thrown at runtime.

What is AggregateException in C#?

AggregateException is used to consolidate multiple failures into a single, throwable exception object. It is used extensively in the Task Parallel Library (TPL) and Parallel LINQ (PLINQ). For more information, see Exception Handling and How to: Handle Exceptions in a PLINQ Query.


2 Answers

If you are able to properly handle the exception within the method the task itself is throwing you should be catching it within that first task, and not in a continuation, unless you have some compelling reason not to do so. Creating a continuation at the same scope as the task itself (as is done in your second example) is needlessly adding more work.

It's either useful or necessary to handle exceptions in continuations when the exception is handled from an entirely different scope than where the task is defined. For example, if you have a method that is given some arbitrary task, and it has no idea what the definition of that task might be, but it needs to do something in the event that the code threw an exception you'll need to have a continuation that handles the exception.

Note that if you are going to have a continuation that handles an exception you can use TaskContinuationOptions.OnlyOnFaulted to only run the continuation when the task throws an exception, rather than doing the check within the definition of the continuation.

like image 149
Servy Avatar answered Oct 14 '22 13:10

Servy


It's largely down to what your design needs. Some things to consider:

Catch exceptions in the tasks that throw them

  • When a task represents some indivisible unit of work that includes cleaning up after particular exception types.
  • When a particular exception type shouldn't propagate outside the task for some reason, e.g. it needs to be wrapped in an outer exception of a different type to meet client code's expectations of the contract.

Handle exceptions in continuations

  • When the exception cleanup should be scheduled by a different TaskScheduler, e.g. running "primary" tasks on the thread pool but marshalling all exception logging onto a UI thread.
  • If it makes sense to have multiple continuations each do different things with the exception, though that would be slightly unusual.
  • To ensure that exceptions from Tasks whose code you don't supply are observed and handled appropriately, e.g. properly cleaning up after tasks created by TaskFactory.FromAsync. Though depending on circumstances, that could as well be done by waiting on the Task.
like image 26
anton.burger Avatar answered Oct 14 '22 12:10

anton.burger