[c#] 비동기 메서드에 의해 throw 된 예외 잡기


2 Answers

예외가 잡히지 않는 이유는 Foo () 메소드가 void 리턴 유형을 가지므로 대기 요청이 호출 될 때 단순히 리턴합니다. DoFoo ()가 Foo의 완료를 기다리지 않기 때문에 예외 처리기를 사용할 수 없습니다.

이것은 메소드 서명을 변경할 수 있다면 더 간단한 솔루션을 열어줍니다.이 코드에서와 같이 Task 유형을 리턴하고 DoFoo()await Foo() 수 있도록 Foo() 변경하십시오.

public async Task Foo() {
    var x = await DoSomethingThatThrows();
}

public async void DoFoo() {
    try {
        await Foo();
    } catch (ProtocolException ex) {
        // This will catch exceptions from DoSomethingThatThrows
    }
}
Question

.NET에서 Microsoft의 비동기 CTP를 사용하면 호출하는 메서드에서 비동기 메서드에 의해 throw 된 예외를 catch 할 수 있습니까?

public async void Foo()
{
    var x = await DoSomethingAsync();

    /* Handle the result, but sometimes an exception might be thrown.
       For example, DoSomethingAsync gets data from the network
       and the data is invalid... a ProtocolException might be thrown. */
}

public void DoFoo()
{
    try
    {
        Foo();
    }
    catch (ProtocolException ex)
    {
          /* The exception will never be caught.
             Instead when in debug mode, VS2010 will warn and continue.
             The deployed the app will simply crash. */
    }
}

그래서 기본적으로 나는 비동기 코드의 예외를 내 호출 코드에 버블 링하여 그 코드가 전혀 가능하지 않게하고 싶습니다.




이 블로그는 문제를 깔끔하게 비동기식 모범 사례에 대해 설명합니다.

비동기 이벤트 처리기가 아닌 한 비동기 메서드에 대한 반환 값으로 void를 사용해서는 안됩니다. 예외가 잡히지 않기 때문에 나쁜 관행입니다.

가장 좋은 방법은 반환 유형을 작업으로 변경하는 것입니다. 또한 모든 방법으로 비동기를 코딩하고 모든 비동기 메서드 호출을 만들고 비동기 메서드에서 호출하도록하십시오. 비동기가 될 수없는 콘솔의 Main 메소드를 제외합니다.

이 모범 사례를 무시하면 GUI 및 ASP.NET 응용 프로그램으로 교착 상태가 발생합니다. 교착 상태는 이러한 응용 프로그램이 하나의 스레드 만 허용하고 비동기 스레드에 전달하지 않는 컨텍스트에서 실행되기 때문에 발생합니다. 즉, GUI는 반환을 위해 동 기적으로 대기하며 비동기 메소드는 컨텍스트 : 교착 상태를 기다립니다.

이 동작은 스레드 풀과 함께 컨텍스트에서 실행되므로 콘솔 응용 프로그램에서는 발생하지 않습니다. 비동기 메서드는 예약 될 다른 스레드에서 반환됩니다. 이것은 테스트 콘솔 응용 프로그램이 작동하지만 다른 응용 프로그램에서 동일한 호출이 교착 상태가되는 이유입니다 ...




또한 비동기 메서드에서 void 반환 유형을 사용하는 경우 예외의 연대순 스택 추적을 잃게된다는 점에 유의해야합니다. 다음과 같이 Task를 반환하는 것이 좋습니다. 디버깅을 훨씬 쉽게 할 수 있습니다.

public async Task DoFoo()
    {
        try
        {
            return await Foo();
        }
        catch (ProtocolException ex)
        {
            /* Exception with chronological stack trace */     
        }
    }



Related