8

After reading information about task and exepcion management, I am using this code to manage an exception thrown in a Task:

Task<Object> myTask = Task.Factory.StartNew<Object>(doTask, CancellationToken.None,   TaskCreationOptions.None, TaskScheduler.Default);
myTask .ContinueWith(task => afterTask(task), TaskScheduler.FromCurrentSynchronizationContext());

Where doTask and AfterTask are:

private <Object> doTask() {
    throw new Exception("BOOM");
}

private afterTask(Task<Object> aTask) {

        if (aTask.IsFaulted)
        {
            MessageBox.Show(aTask.Exception.InnerException.Message);
        }
        else //whatever
}

When Exception Boom is thrown the Visual Studio shows an alert informing that an exception has not been caught but if I continue executing the exception is processed in the afterTask function.

Is this code correct or I missunderstood some basic behaviour of the task? There is any way to avoid the alert from the debugger that the execption has not been caught? Is a bit annoying...

Thanks in advance

Ivan BASART
  • 819
  • 2
  • 11
  • 15

2 Answers2

21

Try this instead:

 task.ContinueWith(
            t =>
            t.Exception.Handle(ex =>
                                   {
                                       logger.Error(ex.Message, ex);
                                       return false;
                                   })

            , TaskContinuationOptions.OnlyOnFaulted
            );

By using the TaskContinuationOptions.OnlyOnFaulted, you run your ContinueWith block only if an exception is thrown by the original task.

Aditionally, you can choose whether to return true or false from the lambda passed to Handle, indicating whether the exception has been handled or not. In my case, I didn't want to stop the exception from propagating. You might want to change it to return true in your case.

dcastro
  • 66,540
  • 21
  • 145
  • 155
  • Thank you very much for your super quick answer. Although the code works it doesn't prevent the debugger from alerting that the exception has not been caught when throwing BOOM. Is there any benefit from using that code instead the one i posted? – Ivan BASART Sep 17 '13 at 10:04
  • In visual studio Debug->Exceptions-> uncheck commonlanguageruntimeexceptions thrown checkbox click ok – Sriram Sakthivel Sep 17 '13 at 10:09
  • The main advantage is the fact that the `ContinueWith` task will only run when an exception is thrown. In the sample you posted, the task would always be run. The second advantage is readability. To prevent those VS popups, I'd try this: http://stackoverflow.com/questions/2173997/how-to-disable-exception-assistant-and-unhandled-exception-popup-in-visual-studi – dcastro Sep 17 '13 at 10:11
-3
        try
        {
            var t1 = Task.Delay(1000);

            var t2 = t1.ContinueWith(t =>
            {
                Console.WriteLine("task 2");
                throw new Exception("task 2 error");
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

            var t3 = t2.ContinueWith(_ =>
            {
                Console.WriteLine("task 3");
                return Task.Delay(1000);
            }, TaskContinuationOptions.OnlyOnRanToCompletion).Unwrap();

            // The key is to await for ALL tasks rather than just
            // the first or last task.
            await Task.WhenAll(t1, t2, t3);
        }
        catch (AggregateException aex)
        {
            aex.Flatten().Handle(ex =>
                {
                    // handle your exceptions here
                    Console.WriteLine(ex.Message);
                    return true;
                });
        }