Task의 예외는 Task에서 Waiting 또는 Exception 속성에 액세스하여 관찰되지 않았습니다. 결과적으로 관찰되지 않은 예외는


100

이것은 무엇을 의미하며 어떻게 해결합니까?

TPL 작업을 사용하고 있습니다.

전체 오류

Task의 예외는 Task에서 Waiting 또는 Exception 속성에 액세스하여 관찰되지 않았습니다. 결과적으로 관찰되지 않은 예외가 종료 자 스레드에 의해 다시 발생했습니다.

System.Threading.Tasks.TaskExceptionHolder.Finalize ()에서

mscorlib

답변:


158

Task를 생성 하고 가비지 수집기에서 작업을 수집 할 때 task.Wait()를 호출 하거나 결과를 검색 하지 않는 Task<T>경우 완료하는 동안 애플리케이션이 해체됩니다. 자세한 내용 은 TPL의 예외 처리에 대한 MSDN 페이지를 참조하십시오 .

여기서 가장 좋은 방법은 예외를 "처리"하는 것입니다. 이 작업은 연속을 통해 수행 할 수 있습니다. 작업에 연속을 연결하고 발생하는 예외를 기록 / 삼킬 수 있습니다. 이것은 작업 예외를 기록하는 깨끗한 방법을 제공하며 간단한 확장 방법으로 작성할 수 있습니다.

public static void LogExceptions(this Task task)
{
    task.ContinueWith( t =>
    {
         var aggException = t.Exception.Flatten();
         foreach(var exception in aggException.InnerExceptions)
             LogException(exception);
    }, 
    TaskContinuationOptions.OnlyOnFaulted);
}

위의 방법을 사용하면 다음을 통해 모든 작업이 앱을 해체하고 로깅하는 것을 방지 할 수 있습니다.

Task.Factory.StartNew( () => 
   { 
       // Do your work...
   }).LogExceptions();

또는 TaskScheduler.UnobservedTaskException을 구독 하고 처리 할 수 ​​있습니다.


17
추가 엔터테인먼트 Off를 위해 선택한 4 글자 단어로 명명 된 클래스에 정적 스텁 메서드 를 사용하고이를 포괄 연속에 사용합니다. 이 특정 예외로 인한 억눌린 좌절감과 싸우는 데 도움이됩니다.
Aaronaught 2011 년

1
@MonsterMMORPG 예-기본적으로 어딘가 에서 예외를 포착하거나 처리해야합니다 . 어딘가에서 처리하는 한 핵심 문제는 사라질 것입니다.
Reed Copsey 2011 년

1
ContinueWith에 대한 호출이 이루어지기 전에 작업에서 예외를 throw 할 수 있습니까?
Tim Sylvester 2012 년

1
@TimSylvester 프레임 워크는 연속이 첨부되기 "전에"발생하더라도 연속을 통해 계속 매핑합니다
Reed Copsey

32
중요 참고 사항 : 이는 .Net 4.0. 예외 처리는 기본적으로 변경되었습니다 .net 4.5응용 프로그램을 해체하지 . 이상에서 볼 .NET 4.5 태스크 예외 처리
i3arnon

43

확실한; 그것은 Task가비지 콜렉션에 남겨진 후 완료되었지만 태스크 자체가 실패했음을 의미합니다. 두 가지 수정 사항이 있습니다.

  • 작업은 (사용 직접 실패 처리 ContinueWith(...)에 가입하고, 확인 .IsFaulted하고 .ExceptionTask매개 변수에서)
  • TaskScheduler.UnobservedTaskException이벤트를 처리하고 관찰 됨으로 표시 ( e.SetObserved()오류를 기록한 후 호출 )

4
한 - 일 또한 포함 - 당신의 계속은 아무것도하지 않고 있지만 확인 된 경우 IsFaulted, 당신이 사용할 수있는 OnlyOnFaulted연속 옵션 및 수동 검사를 피하기 ...
리드 Copsey

실제로 이것은 tpl 작업 내에서 공용 정적 함수를 호출 한 곳에서 발생했습니다. try catch를 사용하면이 문제를 해결할 수 있습니까? 정말 다른 작업을 생성하고 기다려야합니까? 감사합니다
MonsterMMORPG 2011 년

4
SetObservedon UnobservedTaskExceptionEventArgs을 호출해야 함을 언급하는 +1 .
James Webster 2012

-17

이거 한번 해봐:

public static void ThrowFirstExceptionIfHappens(this Task task)
{
    task.ContinueWith(t =>
    {
        var aggException = t.Exception.Flatten();
        foreach (var exception in aggException.InnerExceptions)
        {
            throw exception; // throw only first, search for solution
        }
    },
    TaskContinuationOptions.OnlyOnFaulted); // not valid for multi task continuations
}

public static Task CreateHandledTask(Action action) 
{
    Task tsk = Task.Factory.StartNew(action);
    tsk.ThrowFirstExceptionIfHappens();
    return tsk;
}

5
그것 하나 ??? 무슨 말이야? 당신의 답변이 지금까지의 답변에 어떤 기여를했는지 설명해 주시겠습니까?
Gert Arnold

계속해서 새 작업을 만들었습니다. 그러면 실패하고 같은 상황이됩니다.
Robert Taylor

이 솔루션은 약간 복잡해 보입니다. 아무 이득도없이 의도 치 않게 기능을 숨기고있을 거라고 생각합니다.
Velocitas 2019
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.