내용 보기
작성자
관리자 (IP : 106.247.248.10)
날짜
2023-10-10 13:33
제목
[C#] [스크랩] async 유무에 따른 awaitable 메서드의 병렬 및 예외 처리
간단하게 비동기 함수를 다음과 같이 만들고, namespace ConsoleApp1; internal class Program { static async Task Main(string[] args) { DateTime now = DateTime.Now; await DelayAsync(3); await DelayAsync(6); Console.WriteLine($"{(DateTime.Now - now).TotalSeconds}"); // 3초 + 6초 대기, 총 9초 소요 } static async Task DelayAsync(int id) { await Task.Delay(id * 1000); } }
static async Task Main(string[] args) { DateTime now = DateTime.Now; Task t1 = DelayTask(3); // 3초 작업 시작 Task t2 = DelayAsync(6); // 연이어 6초 작업 시작 await Task.WhenAll(t1, t2); // 6초 소요 Console.WriteLine($"{(DateTime.Now - now).TotalSeconds}"); }
static async Task Main(string[] args) { DateTime now = DateTime.Now; Task t1 = DelayTask(3); // 3초 작업 시작 Task t2 = DelayAsync(6); // 연이어 6초 작업 시작 await t1; // 3초 대기 await t2; // 위의 3초 대기를 포함해 3초 더 대기, 총 6초 소요 Console.WriteLine($"{(DateTime.Now - now).TotalSeconds}"); }
await t2; // 6초 대기 await t1; // 위의 6초 대기 동안에 t1은 이미 종료했으므로 바로 반환
await t1; // t1 작업 대기 후 아래의 코드 실행 await t2;
namespace ConsoleApp1; internal class Program { static async Task Main(string[] args) { DateTime now = DateTime.Now; Task t1 = DelayAsync(3); Task t2 = DelayAsync(6); try { await t1; await t2; } catch (Exception e) { Console.WriteLine(e); Console.WriteLine($"t1.Exception: {t1.Exception}"); Console.WriteLine($"t2.Exception: {t2.Exception}"); } Console.WriteLine($"{(DateTime.Now - now).TotalSeconds}"); } static async Task DelayAsync(int id) { await Task.Delay(id * 1000); throw new InvalidOperationException($"{id} - Exception in DelayAsync"); } } /* 실행 결과 System.InvalidOperationException: 3 - Exception in DelayAsync at ConsoleApp1.Program.DelayAsync(Int32 id) in C:\temp\ConsoleApp1\Program.cs:line 71 at ConsoleApp1.Program.Main(String[] args) in C:\temp\ConsoleApp1\Program.cs:line 17 t1.Exception: System.AggregateException: One or more errors occurred. (3 - Exception in DelayAsync) ---> System.InvalidOperationException: 3 - Exception in DelayAsync at ConsoleApp1.Program.DelayAsync(Int32 id) in C:\temp\ConsoleApp1\Program.cs:line 71 at ConsoleApp1.Program.Main(String[] args) in C:\temp\ConsoleApp1\Program.cs:line 17 --- End of inner exception stack trace --- t2.Exception: 3.0295292 */
try { await t1; await t2; } catch (Exception e) { Console.WriteLine(e); Console.WriteLine($"t1.Exception: {t1.Exception}"); Console.WriteLine($"t2.Exception: {t2.Exception}"); // 이 시점에는 작업이 진행되지 않아 비어 있지만, } Thread.Sleep(3000); Console.WriteLine($"t2.Exception(2nd): {t2.Exception}"); // 이 시점에는 6초 대기가 끝나 예외 정보가 채워져 있음. /* 출력 결과 ...[생략]... t2.Exception: t2.Exception(2nd): System.AggregateException: One or more errors occurred. (6 - Exception in DelayAsync) ---> System.InvalidOperationException: 6 - Exception in DelayAsync at ConsoleApp1.Program.DelayAsync(Int32 id) in C:\temp\ConsoleApp1\Program.cs:line 71 --- End of inner exception stack trace ---
Task t1 = DelayAsync(3); Task t2 = DelayAsync(6); try { await Task.WhenAll(t1, t2); // (3초가 아닌) 6초 대기 후, } catch (Exception e) { Console.WriteLine(t1.Exception); Console.WriteLine(t2.Exception); } /* 출력 결과: System.AggregateException: One or more errors occurred. (3 - Exception in DelayAsync) ---> System.InvalidOperationException: 3 - Exception in DelayAsync at ConsoleApp1.Program.DelayAsync(Int32 id) in C:\temp\ConsoleApp1\Program.cs:line 71 at ConsoleApp1.Program.Main(String[] args) in C:\temp\ConsoleApp1\Program.cs:line 50 --- End of inner exception stack trace --- System.AggregateException: One or more errors occurred. (6 - Exception in DelayAsync) ---> System.InvalidOperationException: 6 - Exception in DelayAsync at ConsoleApp1.Program.DelayAsync(Int32 id) in C:\temp\ConsoleApp1\Program.cs:line 71 --- End of inner exception stack trace --- */
// Task WhenAll의 코드를 직접 구성하는 경우 try { Exception? e1 = null, e2 = null; try { await t1; } catch (Exception e) { e1 = e; } try { await t2; } catch (Exception e) { e2 = e; } if (e1 != null) { throw e1; } if (e2 != null) { throw e2; } } catch (Exception e) { Console.WriteLine($"t1.Exception: {t1.Exception}"); Console.WriteLine($"t2.Exception: {t2.Exception}"); }
C# - 비동기 메서드의 async 예약어 유무에 따른 차이 ; https://www.sysnet.pe.kr/2/0/13421
namespace ConsoleApp1; internal class Program { static async Task Main(string[] args) { DateTime now = DateTime.Now; Task t1 = DelayTask(3); Task t2 = DelayAsync(6); try { await Task.WhenAll(t1, t2); } catch (Exception e) { Console.WriteLine(t1.Exception); Console.WriteLine(t2.Exception); } Console.WriteLine($"{(DateTime.Now - now).TotalSeconds}"); } static Task DelayTask(int id) { Task task = Task.Delay(3000); throw new ApplicationException($"{id} - Exception in DelayTask"); return task; } static async Task DelayAsync(int id) { await Task.Delay(id * 1000); throw new InvalidOperationException($"{id} - Exception in DelayAsync"); } } /* 출력 결과: Unhandled exception. System.ApplicationException: 3 - Exception in DelayTask at ConsoleApp1.Program.DelayTask(Int32 id) in C:\temp\ConsoleApp2\Program.cs:line 31 at ConsoleApp1.Program.Main(String[] args) in C:\temp\ConsoleApp2\Program.cs:line 12 at ConsoleApp1.Program.<Main>(String[] args) */
Task t1;
Task t2;
try
{
t1 = DelayTask(3);
t2 = DelayAsync(6);
await Task.WhenAll(t1, t2);
}
catch (Exception e)
{
Console.WriteLine(t1.Exception);
Console.WriteLine(t2.Exception);
}
|
출처1
https://www.sysnet.pe.kr/2/0/13422
출처2