Я создал небольшую часть кода для параллельной работы нескольких асинхронных операций (сам класс Parallel
не подходит для асинхронных операций).
Он выглядит следующим образом:
public static async Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
var chunks = source.Chunk(dop);
foreach (var chunk in chunks)
await Task.WhenAll(chunk.Select(async s => await body(s).ContinueWith(t => ThrowError(t))));
}
private static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize)
{
while (source.Any())
{
yield return source.Take(chunksize);
source = source.Skip(chunksize);
}
}
private static void ThrowError(Task t)
{
if (t.IsFaulted)
{
if (t.Exception.InnerExceptions != null && t.Exception.InnerExceptions.Count == 1)
throw t.Exception.InnerExceptions[0];
else
throw t.Exception;
}
}
Что касается запуска параллельных задач, приведенный выше код работает очень хорошо. Однако у меня есть некоторые проблемы при исключении исключений.
Код захвата исключений работает хорошо, пока возвращается сообщение об исключении, но трассировка стека оставляет желать многого - поскольку он указывает на метод ThrowError
, а не на метод, который изначально генерировал исключение. Я могу подобрать работу и выяснить, что пошло не так с приложенным отладчиком, но если я когда-нибудь выпущу это приложение, у меня не будет этой опции - в лучшем случае у меня будет исключение с протоколом стека, зарегистрированным.
Итак - есть ли способ получить более значимую трассировку стека при выполнении задач async?
PS. Это для приложения WindowsRT, но я думаю, что проблема не ограничивается WindowsRT как таковой...