방프리
24.01.04 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 28) 본문
Item 28 : async void 메서드는 절대 작성하지 말라
해당 챕터는 C#의 동시성 처리 관련 책을 읽었을 때 그 저자도 강조하던 멘트였다.
(Link : C# 동시성 프로그래밍 (Concurrency in C# Cookbook)
https://book.interpark.com/product/BookDisplay.do?_method=detail&sc.saNo=001&sc.prdNo=349595515&product2020=true)
그 이유는 async void는 대기할 수 없다. 즉, 앞 챕터에서 이야기 했던 async await의 장점을 살릴 수가 없다.
그럼에도 불가피하게 사용해야하는 경우가 있는데 바로 비동기 이벤트 핸들러를 만들 때이다.
async void를 사용하지 않아야 하는 이유 중 또 하나는 Task를 통해 대기할 수 없기 때문에 예외가 발생할
경우 대처가 불가능하다. 그러므로 async void를 사용할 땐 절대 예외가 있어서는 안된다.
만약 예외가 발생하게 된다면 SynchronizationContext가 죽어버린다. 그러면 어떻게 해야될까?
예외를 외부로 던지도록하는 것이 좋다.
private async void OnCommand(object sender, RoutedEventArgs e)
{
var viewModel = (DataContext as SampleViewModel);
try
{
await viewModel.Update();
}
catch (Exception ex) when (logMessage(viewModel, ex))
{
}
}
private bool logMessage(SampleViewModel viewModel, Exception ex)
{
viewModel.Messages.Add(ex.ToString());
return false;
}
public static class Utilities
{
public static async void FireAndForget(this Task,
Action<Exception> onErrors)
{
try
{
await task;
}
catch (Exception ex)
{
onErrors(ex);
}
}
public static async void FireAndForget(this Task task,
Func<Exception, bool> onoError)
{
try
{
await task;
}
catch (Exception ex) when (onError(ex))
{
}
}
}
//만약 특정 예외 타입에 대처할 수 없는 가정이라면
//특정 예외타입을 제네릭 타입으로 만들자
public static async void FireAndForget<TException>
(this Task task,
Action<TException> recovery,
Func<Exception, bool> onError)
where TException : Exception
{
try
{
await task;
}
catch (Exception ex) when (onError(ex))
{
}
catch (TException ex2)
{
recovery(ex2);
}
}
다시 강조하지만 async void에서 예외가 발생했을 땐 어쩔 수 없이 프로그램이 중단되어야 한다. 하지만 그 중단을
최대한 안전한 방향으로 이끄는 방법밖에 대처할 수 없다. 그러므로 왠만하면 사용하지 말자!
'C# > More Effective C#' 카테고리의 다른 글
24.01.12 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 30) (2) | 2024.01.12 |
---|---|
24.01.07 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 29) (0) | 2024.01.07 |
24.01.04 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 27) (1) | 2024.01.04 |
24.01.02 Chapter2. API 설계 (Item 26) (0) | 2024.01.02 |
24.01.01 Chapter2. API 설계 (Item 25) (0) | 2024.01.01 |
Comments