Не ловится исключение в списке асинхронных методов
Есть форма, при её создании выполняется код:
public MainForm()
{
InitializeComponent();
Test();
}
async Task Test ()
{
try
{
await IAmException();
}
catch (Exception e)
{
e.ShowMessageBox();
}
}
async Task<int> IAmException()
{
throw new NotImplementedException();
return 0;
}
Запускаю этот код, всё норм – исключение ловится, показывается сообщение об ошибке. Изменяю его так:
async Task Test ()
{
try
{
var TaskList = await ExceptionGenerator(1);
TaskList.ForEach(t => t.Start());
await Task.WhenAll(TaskList);
}
catch (Exception e)
{
e.ShowMessageBox();
}
}
async Task<List<Task<Task<int>>>> ExceptionGenerator(int Size)
{
var sampleData = new int[Size].FillAndGet(0); //:Заполняет всю матрицу указанным числом
var tasks = new List<Task<Task<int>>>(Size);
foreach (var data in sampleData)
{
tasks.Add(new Task<Task<int>>(async () => await IAmException(data)));
}
return tasks;
}
async Task<int> IAmException(int data)
{
throw new NotImplementedException();
return data;
}
Вижу, что срабатывает точка останова в throw new NotImplementedException();, продолжить... и всё! catch это исключение почему-то не поймало. Почему исключение улетело в молоко? Я же ожидаю завершения всех тасков внутри try-catch.
Пробовал делать так:
async Task Test ()
{
try
{
//(await BenchmarkSites.Passmark.GetAll(_selectedType)).ForEach(h => h.RunSynchronously(TaskScheduler.Current));
var TaskList = (await ExceptionGenerator(1));
TaskList.ForEach(t => t.Start());
var waitAll = Task.WhenAll(TaskList);
await waitAll;
waitAll.Exception?.ShowMessageBox();
}
catch (Exception e)
{
e.ShowMessageBox();
}
}
При дебаге видно, что waitAll.Exception is null
Ответы (2 шт):
Я бы переписал это под делегаты и не мучал конструктор таска.
async Task Test()
{
try
{
var delegates = await ExceptionGenerator(1);
var taskList = delegates.Select(f => Task.Run(f));
await Task.WhenAll(taskList);
}
catch (Exception e)
{
e.ShowMessageBox();
}
}
async Task<List<Func<Task<int>>>> ExceptionGenerator(int Size)
{
var sampleData = new int[Size];
var tasks = new List<Func<Task<int>>>(Size);
foreach (var data in sampleData)
{
tasks.Add(async () => await IAmException(data));
}
return tasks;
}
async Task<int> IAmException(int data)
{
throw new NotImplementedException();
return data;
}
TaskList имеет тип List<Task<Task<int>>>.
В этой строке
await Task.WhenAll(TaskList);
эвейтятся только внешние задачи.
Перепишем эту строку следующим образом:
var x = await Task.WhenAll(TaskList);
Здесь x - Task<int>[] - массив задач. Их тоже нужно ожидать.
Добавим их ожидание:
await Task.WhenAll(x);
Вот теперь код работает.
Написано слишком мудрёно. Поэтому код лучше переписать.