//반복 각각의 오류에 영향받지 않고 수행
#pragma warning disable CS1998 // 이 비동기 메서드에는 'await' 연산자가 없으며 메서드가 동시에 실행됩니다.
public static Task TryEach<T>(this IEnumerable<T> e, Action<T> a) => Task.WhenAll(e.Select(async i => a(i)));
public static Task TryEach(IEnumerable<Action> actions) => Task.WhenAll(actions.Select(async a => a()));
#pragma warning restore CS1998 // 이 비동기 메서드에는 'await' 연산자가 없으며 메서드가 동시에 실행됩니다.
public static Task TryEach<T>(this IEnumerable<T> e, Func<T,Task> f) => Task.WhenAll(e.Select(async i => await f(i)));
public static Task TryEach(IEnumerable<Func<Task>> actions) => Task.WhenAll(actions.Select(async a => await a()));
반복적인 처리를 함에 있어 하나가 에러가 발생하면 이후의 처리까지 끊겨버린다. Parallel을 이용해도 어쨋든 예외 하나가 다른 처리까지 방해했다.
async Task로 선언된 매서드는 실제로는 비동기매서드가 아니라 하더라도 외부에서 반환Task를 wait이나 await 하기전까진 에러가 전파되지 않기때문에
반복할 함수를 async 로 덮고 WhenAll 하면 일부 구간에서 에러가 나더라도 일단 처음부터 끝까지 각각의 시도는 독립적으로 하게된다.
그리고서 WhenAll이 모아둔 Task 하나를 무시하고 넘기거나 a/wait 함으로써 봉인해둔 익셉션을 한꺼번에 핸들링 하게 되는것이다.
편법적인 방법이라 await없는 async method에 대한 warring을 숨길 필요가 있어 전처리자도 삽입.
이러한 패턴을 공식적으로 지원하는 모델이 있는지 확인필요
내부에 await이 없는 async void는 throw시 또 에러가 나던데 어떻게 이해하면 되는건지 잘 모르겠음. 그건 그냥 안쓰는걸로
동기의 경우 Task.WaitAll 이나 Parallel을 쓰면 AggregateException으로 취합까지 다해줌, 비동기는 취합을 알아서 해야댐..