디버깅 시스템.AggregateException - 비동기식 코드에서도 마찬가지입니다.

12833 단어 csharpdotnet
제가 다시 여기서 common 디버깅을 도와드릴게요.순전히 예외다.이번에 나는 당신이 이 상당히 통용되는 시스템을 디버깅하는 것을 도와주고 싶습니다.집합 이상.말 그대로 AggregateException은 단일 이상에서 하나 이상의 이상을 일괄 처리하는 데 사용됩니다.이 글에서, 이 이상이 발생한 원인과 C 코드에서 디버깅하는 방법을 보여 드리겠습니다.

오류 발생 및 처리


새로운 AggregateException 을 강제하는 것부터 시작합시다.이상 재중 대량 사용.NET의 작업 라이브러리에서 작업과 관련된 예제를 선택하는 이유는 다음과 같습니다.
Task task1 = Task.Factory.StartNew(() => { throw new ArgumentException(); } );
Task task2 = Task.Factory.StartNew(() => { throw new UnauthorizedAccessException(); } );

try
{
    Task.WaitAll(task1, task2);
}
catch (AggregateException ae)
{
}
위의 예시에서 우리는 두 개의 임무를 시작했는데, 모든 임무는 이상을 일으킬 것이다.전화WaitAll하면 알 수 있어요.NET는 두 작업의 결과를 호출하고 기다립니다.이 두 임무의 조합 결과는 AggregateException 이 될 것이다.
다음 오류 메시지 중 하나에 따라 이 문서를 읽을 수 있습니다.
  • 시스템.AggregateException: 하나 이상의 오류가 발생했습니다.
  • 작업 취소
  • "시스템입니다.mscorlib에서 AggregateException이 발생합니다.dll
  • 다음 절에서, 나는 당신에게 모든 문제를 어떻게 디버깅하고 복구하는지 보여 드리겠습니다.

    디버그 오류


    디버거에서 이전 예시의 이상을 검사할 때, 우리는 InnerExceptions 속성에서 두 개의 던져진 이상을 보았다.

    이름에서 약속한 바와 같이 AggregateException 다른 예외적인 포장이다.이 예에서는 ArgumentExceptionUnauthorizedAccessException 을 내부 이상으로 사용할 수 있습니다.
    경우에 따라 각 예외에 catch 블로그가 다음과 같이 추가됩니다.
    try
    {
        ...
    }
    catch (ArgumentException ex1)
    {
        // Log and re-throw
    }
    catch (UnauthorizedAccessException ex2)
    {
        // Log and swallow
    }
    
    이런 방식을 통해 사용자에게 단일 오류 메시지를 생성하고 이상을 기록할 수 있지만, 그 중 하나 또는 세 번째 메시지만 다시 던질 수 있습니다.InnerExceptions 속성에서 각 이상을 순환하는 것과 달리 AggregateExceptionHandle 라는 간편한 도우미 방법을 제공합니다.
    try
    {
        ...
    }
    catch (AggregateException ae)
    {
        ae.Handle(inner =>
        {
            // Log inner
            ...
            return inner is UnauthorizedAccessException;
        });
    }
    
    이 예에서 Handle 방법은 모든 이상을 기록한다.func 각 예외가 처리되었는지 여부를 나타내는 반환bool이 필요합니다.이 예에서 우리는 Handle 방법 처리UnauthorizedAccessException를 알려주지만 처리하지 않는다ArgumentException.이로 인해 AggregateException 리셋 코드가 던져지지만 UnauthorizedAccessException 속성에 InnerExceptions 이 없습니다. (이 이상을 처리된 것으로 표시했기 때문입니다.)

    HttpClient의 집합 이상

    System.Net.Http.HttpClient 클래스를 처리할 때 체험할 수 있습니다 AggregateException.이는 주로 기존 APIWait,ContinueWith 등)를 사용하여 비동기식 코드를 구현할 때입니다.예를 들어 보겠습니다.
    try
    {
        var client = new HttpClient();
        var task = client.GetStringAsync("https://httpstat.us/500");
        task.Wait();
        var result = task.Result;
    }
    catch (AggregateException ex)
    {
        throw ex;
    }
    
    https://httpstat.us/500에 대한 요청은 HTTP 상태 코드500로 되돌아오며, 이 코드는 하나HttpRequestException를 던집니다.나는 GetStringAsync 방법을 예로 들지만, 만약 다른 비동기 메시지, 예를 들어 PostAsync를 사용한다면 코드는 유사해 보일 것이다.전술한 바와 같이 작업 API의 이상은 AggregateException 에 포장되고 InnerExceptions 속성에 HTTP 이상이 포함됩니다.
    실제 이상을 얻으려면 일련의 옵션이 있습니다.나는 이상 기록을 반복해서 설명할 것이다.이전 예제에서 보여준 Handle 방법부터 살펴보겠습니다.
    try
    {
        ...
    }
    catch (AggregateException ex)
    {
        ex.Handle(inner =>
        {
            if (inner is HttpRequestException)
            {
                // Log the exception
    
                return true;
            }
    
            return false;
        });
    }
    
    내부 이상이 HttpRequestException 유형에 속하는지 확인하고 있습니다. 이 경우 Handle 방법을 알려주십시오. 이 이상은 이미 처리되었습니다.다른 장면에서 나는 Handle 원시 이상을 다시 던지라고 말했다 false.
    다른 방법은 ContinueWith 방법으로 포착하고 처리하는 것이다AggregateException:
    var client = new HttpClient();
    var task = client
        .GetStringAsync("https://httpstat.us/500")
        .ContinueWith(t =>
        {
            try
            {
                return t.Result;
            }
            catch (AggregateException ex)
            {
                ex.Handle(inner =>
                {
                    if (inner is HttpRequestException)
                    {
                        // Log the exception
    
                        return true;
                    }
    
                    return false;
                });
            }
            catch (Exception ex)
            {
                throw ex;
            }
    
            return null;
        });
    task.Wait();
    var result = task.Result;
    
    나는 기본적으로 이전의try-catch를 ContinueWith 방법으로 옮겼을 뿐이다.
    마지막으로, 네가 있다면.NET 4.5 (아마도 그렇지 않을 경우) 키워드를 사용할 수 있습니다 await.
    var client = new HttpClient();
    try
    {
        var result = await client.GetStringAsync("https://httpstat.us/500");
    }
    catch (HttpRequestException ex)
    {
        // Log the exception
    }
    catch (Exception ex)
    {
        throw ex;
    }
    
    
    코드가 HttpRequestException 가 아니라 AggregateException 를 어떻게 포착하는지 주의하십시오.왜냐면NET가 자동으로 켜짐AggregateException 및 베이스 예외를 내보냅니다.대부분의 경우, 이것이 바로 네가 원하는 것이다.기존 비동기 코드를 이식하여 await 키워드를 사용하는 또 다른 장점.
    이 시리즈의 다른 게시물을 읽어야 합니다: Debugging common .NET exceptions.

    사용자가 더 적은 오류를 원하십니까?


    엘마.io는 간단한 오류 기록과 정상적인 운행 시간 감시 서비스입니다.순액모든 사람에 대한 지원을 통해 오류를 다시 제어합니다.NET 웹 및 로그 프레임워크
    ➡️ Error Monitoring for .NET Web Applications ⬅️
    이 문장은 먼저 《elmah》에 나타났다.io 블로그https://blog.elmah.io/debugging-system-aggregateexception-even-in-async-code/

    좋은 웹페이지 즐겨찾기