0

I have been reading around a bit, such as here (Catch an exception thrown by an async void method) and I thought the behaviour of async Task methods was:

  1. that you could try/catch them as normal when using await or Task.Wait e.g. try{ await X();}catch(Exception SqlException e){...}
  2. if you let it 'bubble up' you will instead get AggregateException

But I am finding my application is just terminating without breaking on exceptions at all. My code looks like:

    internal async Task RunAsync()
    {
        var tasks = monitors.Select((p) => p.Value.MonitorAsync()).ToList();
        await Task.WhenAny(tasks);
        Console.WriteLine("ONE");
    }

    public static async Task Main(string[] args)
    {
        var app = new App();
        try
        {
            await app.RunAsync();
            Console.WriteLine("TWO");
        }
        catch(Exception e)
        {
            Console.WriteLine(e);
        }
    }

Setting breakpoints on "ONE" and "TWO" I can see that tasks has at least one Task with status Faulted, and t has status RanToCompletion. So the fault state is lost and no exceptions.

Clearly I'm missing something obvious, what should I be doing differently?

BTW WhenAny is used to detect unusual termination, these tasks should only ever exit due to failure. This is more of a test-bed to understand catching exceptions.

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589

1 Answers1

2

This is because of WhenAny. Please check the documentation:

The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state. (emphasis mine)

This means that WhenAny will not raise an exception if any of the tasks faults.

This is contrary to WhenAll, which will raise an exception if any of the tasks it waits for faults with an unhandled exception.

Nick
  • 4,787
  • 2
  • 18
  • 24
  • THanks, this makes sense when you think about it... WhenAny is completing normally if one task fails, WhenAll is completing abnormally. So, is your suggestion I should simply use `WhenAll` instead, or are there other good options? – Mr. Boy Jun 02 '20 at 12:46
  • 1
    `WhenAny` is good when you just want to continue when any tasks runs to completion one way or another. If you want to check if any task has failed, then you should use `WhenAll`, this is the proper practice. – Nick Jun 02 '20 at 13:04