Home > Enterprise >  Exception handling using tasks and Task.WaitAny
Exception handling using tasks and Task.WaitAny

Time:02-02

Task.WaitAll method can throw an AggregateException, but Task.WaitAny method does not.

Questions:

  1. I do not understand for what purpose the developers of the framework did this?
  2. How to catch an exception from a task using Task.WaitAny method?

Example:

using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            void MyMethodForDivideByZeroException()
            {
                int a = 1;
                a = a / 0;
            }

            void MyMethodForIndexOutOfRangeException()
            {
                int[] MyArrayForInt = new int[2] { 1, 2 };
                Console.WriteLine(MyArrayForInt[2]);
            }

            Task MyTask22 = new Task(MyMethodForDivideByZeroException);
            Task MyTask23 = new Task(MyMethodForIndexOutOfRangeException);

            MyTask22.Start();
            MyTask23.Start();

            Task.WaitAny(MyTask22, MyTask23); //No exceptions
            //Task.WaitAll(MyTask22, MyTask23); //AggregateException

            Console.WriteLine(MyTask22.Status);
            Console.WriteLine(MyTask23.Status);
        }
    }
}

CodePudding user response:

WaitAny() waits for any one of the tasks to complete (successfuly or otherwise).
When one does, with an exception, the exception is not propagated (thrown).

WaitAll() waits for all of the tasks to complete.
As they both throw an exception, these are aggregated into an AggregateException.

You can check for errors like this:

var tasks = new[] { MyTask22, MyTask23 };
int taskIndex = Task.WaitAny(tasks); //No exceptions
        
if (taskIndex >= 0)
{
    throw tasks[taskIndex].Exception;
}

More useful information here:

CodePudding user response:

The job of the Task.WaitAny method is to inform you that a task has completed, not that a task has completed successfully.

I'll answer your questions in reverse order:

  1. How to catch an exception from a task using Task.WaitAny method?

You probably ask how to throw the exception of a completed task that has failed. The simplest way is probably just to Wait the task:

var tasks = new Task[] { MyTask22, MyTask23 };
int completedTaskIndex = Task.WaitAny(tasks);
tasks[completedTaskIndex].Wait();
  1. I do not understand for what purpose the developers of the framework did this?

Because otherwise the method would not be able to do its intended job. You won't be able to use this method in order to be informed about the completion of a task. Instead of getting the index of the completed task, you would get a useless and expensive exception. You could catch this exception, but you would still don't know which of the tasks is the one that caused the exception.

  •  Tags:  
  • Related