'async void'이벤트 핸들러를 피해야합니까?


119

async void작업을 시작 하기 위해 fire-and-forget 메서드 를 사용하는 것은 일반적으로 나쁜 생각으로 간주된다는 것을 알고 있습니다 . 대기중인 작업에 대한 추적이없고 그러한 메서드 내부에서 발생할 수있는 예외를 처리하는 것이 까다롭기 때문입니다.

일반적으로 async void이벤트 핸들러도 피해야 합니까? 예를 들면

private async void Form_Load(object sender, System.EventArgs e)
{
        await Task.Delay(2000); // do async work
        // ...
} 

다음과 같이 다시 작성할 수 있습니다.

Task onFormLoadTask = null; // track the task, can implement cancellation

private void Form_Load(object sender, System.EventArgs e)
{
        this.onFormLoadTask = OnFormLoadTaskAsync(sender, e);
} 

private async Task OnFormLoadTaskAsync(object sender, System.EventArgs e)
{
        await Task.Delay(2000); // do async work
        // ...
} 

재진입 가능성 외에 비동기 이벤트 핸들러의 수중 암석은 무엇입니까?


그래야하지만 할 수 없습니다. 그 외에도 async void를 사용할 때 취해야하는 모든주의 사항은 이미 UI 이벤트 처리기에 필요합니다.
Paulo Morgado

그리고 재진입은 async-await 자체를 사용하는 것이 아니라 이벤트 핸들러에 의해 발생한 비동기 작업으로 인해 발생합니다.
Paulo Morgado

답변:


153

가이드 라인은 이벤트 핸들러에서 사용하는 경우를 async void 제외하고 는 피하는 것이므로 이벤트 핸들러에서 사용 async void하는 것은 괜찮습니다.

즉, 단위 테스트를 위해 모든 async void메서드 의 논리를 고려하는 경우가 많습니다 . 예 :

public async Task OnFormLoadAsync(object sender, EventArgs e)
{
  await Task.Delay(2000);
  ...
}

private async void Form_Load(object sender, EventArgs e)
{
  await OnFormLoadAsync(sender, e);
}

궁금한데 ...에 Form_Load대한 액세스 권한을 변경하지 않는 이유 가 public있습니까? 그런 식으로 코드가 덜 장황한 것 같습니다.
InteXX

죄송합니다, 신경 쓰지 마세요 ... VBer가 여기서 C #을 읽으려고합니다 ... 방금 반환 유형이 OnFormLoadAsync. 나는 이것이 편리한 트릭을 만든다는 것을 알았다. 감사.
InteXX

여기에서 한 번 살펴보고 의견을 제시해 주시겠습니까 ? 감사!
InteXX

2
@ AlexHopeO'Connor : Handled플래그 동 기적으로 설정 되어야합니다 . async이벤트 처리 여부를 결정하는 데 사용할 수 없습니다.
Stephen Cleary

2
@ AlexHopeO'Connor : WPF 앱으로 작업 한 지 오래되었지만 과거와 비슷한 솔루션을 사용했습니다. 즉, ICommand.Execute방법을 만드십시오 async void. 이후이 허용 생각 ICommand.Execute이다 논리적으로 이벤트 핸들러.
Stephen Cleary

50

일반적으로 비동기 무효 이벤트 핸들러도 피해야합니까?

일반적으로 이벤트 핸들러는 void 비동기 메서드가 잠재적 인 코드 냄새가 아닌 경우입니다.

이제 어떤 이유로 작업을 추적해야하는 경우 설명하는 기술이 완벽하게 합리적입니다.


6

예, 일반적으로 이벤트 핸들러의 비동기 무효가 유일한 경우입니다. 그것에 대해 더 알고 싶다면 여기 채널 9에서 멋진 비디오를 확인하십시오.

The only case where this kind of fire-and-forget is appropriate is in top-level event-handlers. Every other async method in your code should return "async Task".

여기에 링크가 있습니다


' 최상위 이벤트 처리자 '는 중요한 힌트입니다. 낮은 수준의 이벤트 처리기에서 async void 이벤트 처리기를 사용하면 예외가 발생하지 않는 큰 문제가 발생할 수 있습니다.
Portikus 2011

비디오 링크 주셔서 감사합니다. 매우 유용합니다
lsp

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.