none
Task is not capturing exceptions thrown RRS feed

  • Question

  • I have the following code:

    Task<Shared.Types.AzureStorage.Product> t3 = Task.Factory.StartNew<Shared.Types.AzureStorage.Product>(() => { CatalogEntities context = new CatalogEntities(); CatalogProducts source = context.CatalogProducts.FirstOrDefault(p => p.SKU == sku); . . . .

    context.Dispose(); return destination; }); try { Task t4 = t3.ContinueWith((ant) => { // Create the TableOperation that inserts the customer entity. TableOperation insertOperation = TableOperation.Insert(ant.Result); // Execute the insert operation. table.Execute(insertOperation); totalCount++; }); } catch (AggregateException aggEx) { foreach (Exception ex in aggEx.InnerExceptions) { if (ex is StorageException) { DumpStorageException(ex as StorageException); } else { Debug.WriteLine(ex.ToString()); } } errorCount++; }



    The problem is that the line .....FirstOrDefault() gets an EntityException that VisualStudio claims is 'Unhandled' so it never makes it to the ContinueWith task to 'observe' the task and catch the exception. What am I missing?


    Kevin Burton

    Wednesday, January 9, 2013 5:10 PM

Answers

  • Hi Kevin,

    How about this code snippet:

                Task a = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("a starting");
                    throw new Exception();
                    //. . . . . .
                });
                Task b = a.ContinueWith((ant) =>
                {
                    Console.WriteLine("b");
                    //. . . . .       
            });
                Task c = b.ContinueWith((ant) =>
                {
                    Console.WriteLine("c");
                    //. . . . . .
                });
                try
                {
                    Task.WaitAll(new Task[] { a, b, c });
                }
                catch (AggregateException aex)
                {
                    Console.WriteLine(  aex.Message);
                    //. . . .
                }

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, January 23, 2013 10:17 AM
    Moderator

All replies

  • Hi Kevin,

    Please have a look at this link, here you will get your query resolved:

    http://msmvps.com/blogs/brunoboucard/archive/2010/11/06/parallel-programming-with-c-4-0-part-3.aspx


    Regards, http://www.shwetalodha.blogspot.in/

    Thursday, January 10, 2013 4:47 AM
  • I am not sure where to look. This link seems to deal mainly with cancelations. I did find this quote:

                The type of the exceptions thrown in the .NET 4.0 parallel framework is AggregateException since it is possible in parallel programming that several tasks simultaneously throw an exception. To find out what exceptions are thrown, we iterate over the InnerExceptions collection. If you run this code, you will get a result similar to the one below.
    
    

    But this just confirms what I thought should happen. What am I missing. Hints?


    Kevin Burton

    Thursday, January 10, 2013 5:02 AM
  • Hi Kevin,

    How about surrounding the t3 in the try catch? And why did not you try that?

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Thursday, January 10, 2013 5:18 AM
  • Thank you. That is not how I understood it. I understood that the exception would be captured in the Task and would be thrown as an AggregateException when the task is "observed" (with wait, result, etc.). Is this not so?


    Kevin Burton

    Thursday, January 10, 2013 5:44 AM
  • Thank you. That is not how I understood it. I understood that the exception would be captured in the Task and would be thrown as an AggregateException when the task is "observed" (with wait, result, etc.). Is this not so?


    Kevin Burton

    Take read by Stephen Toub. If the with in the task, it does not handle the exception then it will continue to bubble up unless you either use on the mechanism mentions such as a continuations that does the OnError or the IgnoreExceptions.

    What is currently happening is first task runs and exception is thrown and there is no try catch in its context (the anonymous delegate). Therefore the exception is stored in the tasks and the task looks for something to continue with to handle the exception. There is nothing and therefore when the Task is GC it sees it and throws an unhandled exception.

    Thanks,

    Brad

    Thursday, January 10, 2013 5:22 PM
  • Thanks again. I know I am being slow but when is the exception stored in the AggregateException? If I store the Task in a collection (the final task in the contue chain) and Wait on the tasks in the collection is the exception observed and then not unhandled?

    Kevin Burton

    Thursday, January 10, 2013 6:09 PM
  • From Stephen's article "As such, any unhandled exceptions will be stored into the relevant Task instance, later thrown any time that Task is waited on (and also available through the Task’s Exception property)."

    Since you are not waiting for the task aka Task.Wait it will not thrown. Therefore if you did like a t3.Wait then you could expect that exception to be thrown. That is why in Shweta Jain's link it does the task.Wait and will catch the exception. You need to do a continue with and handle the error or simply ignore it and handle it in your continue with.

    Thanks,

    Brad

    Thursday, January 10, 2013 6:31 PM
  • So this will handle the exception:

                                Task<OrderBase> t3 = Task.Factory.StartNew<OrderBase>((id) =>
                                    {
                                        . . .
                                    }, (Guid)g);
                                Task<string> t4 = t3.ContinueWith<string>((ant) =>
                                {
    . . . . .
                                });
                                innerTaskList.Add(t4.ContinueWith((ant) =>
                                {
     . . . .
                                }));
    . . . . . . .
    
                tasks = innerTaskList.ToArray();
                while (tasks.Length > 0)
                {
                    try
                    {
                        int idx = Task.WaitAny(tasks);
     . . . . .
                        tasks = tasks.Where((t) => t != tasks[idx]).ToArray();
                    }
                    catch (AggregateException aggEx)
                    {
    . . . . .
                    }
                }
    
    Now there is a Wait so the exception should not be unhandled. Right?

    Kevin Burton

    Thursday, January 10, 2013 6:41 PM
  • I don't think it will because the task that you are adding is the new task after t4, which the exception occurs in t3 and the try/catch/wait is on the t5 tasks. You can try because I'm not 100% but you might just want to add all items to the list.

    Thanks,

    Brad

    Thursday, January 10, 2013 8:02 PM
  • So in each ContinueWith anonomous delegate block I need to "observe" the task by accessing Result or Exception, or Wait on the task (which doesn't make much sense since it is assumed that the task is finished since that is the point of contunuations). The put a try/catch block around the "observation" since that is where the exception will be thrown. Right? Something like:

    Task<string> t4 = t3.ContinueWith<string>(() =>
    {
        try
        {
            result = t3.Result;
            . . . . .
        }
        catch(AggregateException aggEx)
        {
            . . . . .
        }
    
    });
    It seems that the problem is with exceptions thrown in continuations or in Tasks that have continuations. Do you have any comments on that?

    Kevin Burton


    • Edited by KevinBurton Friday, January 11, 2013 7:13 PM Update
    Thursday, January 10, 2013 8:21 PM
  • Hi ,

    》The put a try/catch block around the "observation" since that is where the exception will be thrown. Right?

    Yes. I do think so.

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Tuesday, January 22, 2013 11:25 AM
  • The problem is that the exception doesn't seem to wait for the "observation".

    Task a = Task.Factory.StartNew(() =>
    {
    throw new Exception();
    . . . . . .
    });
    Task b = a.ContinueWith((ant) =>
    {
    . . . . .
    });
    Task c = b.ContinueWith((ant) =>
    {
    . . . . . .
    });
    try
    {
       c.Result();
    }
    catch(AggregatedException aex)
    {
    . . . .
    }

    The "observation" is in a try catch block. But if the exception is thrown as indicated in the delegate for Task a then it is "unhandled" and never is aggregated untill the "observation. At least that is what I am seeing.


    Kevin Burton

    Tuesday, January 22, 2013 1:53 PM
  • Hi Kevin,

    How about this code snippet:

                Task a = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("a starting");
                    throw new Exception();
                    //. . . . . .
                });
                Task b = a.ContinueWith((ant) =>
                {
                    Console.WriteLine("b");
                    //. . . . .       
            });
                Task c = b.ContinueWith((ant) =>
                {
                    Console.WriteLine("c");
                    //. . . . . .
                });
                try
                {
                    Task.WaitAll(new Task[] { a, b, c });
                }
                catch (AggregateException aex)
                {
                    Console.WriteLine(  aex.Message);
                    //. . . .
                }

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, January 23, 2013 10:17 AM
    Moderator