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

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

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

전체 오류

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

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

mscorlib



답변

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을 구독 하고 처리 할 수 ​​있습니다.


답변

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

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

답변

이거 한번 해봐:

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;
}


답변