Search code examples
c#exceptiontask-parallel-libraryparallel.foreach

Why does an exception in an async Parallel.ForEach crash the application?


Why does the following crash if run inside a console application instead of throwing an AggregateException and being caught by the outer try/catch?

I've simplified the use case for the await for brevity, but in the relevant code I am indeed trying to execute an awaitable Task of importance.

var list = new List<string>() {"Error"};

        try
        {
            Parallel.ForEach(list, new ParallelOptions()
            {
                MaxDegreeOfParallelism = 8
            }, async listEntry =>
            {
                await Task.Delay(5000);
                throw new Exception("Exception");
            });
        }
        catch (Exception ex)
        {
            //never hits, the application crashes
        }

        Console.ReadLine();

I note that the following does not cause the application to fail, and an exception is indeed caught, but I do not understand what's really going on as to what is fundamentally different about the two contexts:

var list = new List<string>() {"Error"};

        try
        {
            Parallel.ForEach(list, new ParallelOptions()
            {
                MaxDegreeOfParallelism = 8
            }, listEntry =>
            {

                throw new Exception("Exception");
            });
        }
        catch (Exception ex)
        {
            //exception is caught, application continues
        }

        Console.ReadLine();

Solution

  • As already mentioned in comments, you shouldn't mix async and Parallel.ForEach, they don't work together.

    What you're observing is one of the consequences of that: the lambda is compiled as an async void method and when an async void method throws, the exception is rethrown on its SynchronizationContext, which will normally crash the application.