다음은 .NET 4.0 및 기본 TaskScheduler 사용을 가정합니다. 모든 통지
첫째는 예외은 통과 내부 대표를 제기하는 것을, 그래서 그들은하지 당신이 (논리적으로) 당신의 catch
하고있는 일에 다른 스레드에서 발생합니다. 그래서 어떻게 든 예외는 스레드/작업을 시작한 델리게이트/람다 코드를 실행하는 스레드에서 전파되어야합니다.
Task
에 대해 라이브러리는 자신의 스레드가 아닌 스레드를 호출하도록 선택할 수 있다고 생각합니다. (단, Parallel.ForEach
등의 경우에만 해당됩니다. "알몸"이 아닌 Task
개체).
두 개의 일이 들어
은 두 가지가 충족되어야합니다
- 호출 스레드가 여전히 활성 상태입니다. 그렇지 않으면 실제로 캐치를 수행 할 수있는 것이 아무것도 없습니다.
- 스레드/작업에서 발생한 예외는 어떻게 든 유지되어야하며 예외를 잡을 수는 없습니다.
그렇다면 두 예제 모두 스레드/작업 완료를 기다리지 않아도됩니다. 첫 번째 예에서는 task.Wait()
(또는 이와 유사한 것)이 누락되었으며 두 번째 예에서는 thread.Join()
이 누락되었습니다. 테스트 코드 타이밍 동작에 따라 스레드/태스크 (위의 항목 1)에서 예외를 관찰 할 수 없을 수도 있습니다.
작업 예 : 당신은 두 통화를 추가
경우에도이 나 (다시 .NET 4.0)에 대한 일어나는 것이다 task.Wait()
에 대한 호출이 실제로 원래 작업의에서 처리되지 않은 왼쪽 예외를 재발생 델리게이트 (이것은 TPL이 당신을 위해 내부적으로 수행하는 것입니다), System.AggregateException
안에 포장합니다. 좀 더 정밀한 것을 사용하고 평평한 "catch-all"을 사용하면 볼 수 있습니다.
스레드 예 : 대리인에 의해 제기 예외가 처리되지 않은 남아 즉
(당신이 unhandled exceptions differently 다루는 아무것도하지 않는 한) 다음과 같이 응용 프로그램이 종료 나는 예제를 할 것이다 :
// Thread example
var thread = new Thread(() => { throw null; });
thread.Start();
thread.Join();
// Should never reach here, depending on timing sometimes not even
// until the Join() call. The process terminates as soon as the other
// thread runs the "throw null" code - which can logically happen somewhere
// after the "start" of the "Start()" call.
// Task example
try
{
var task = new Task(() => { throw null; });
task.Start();
task.Wait();
}
catch (AggregateException ex)
{
Console.WriteLine("Exception: " + ex);
}
버전 번호를 5.0에서 4.5로 변경했습니다. 괜찮습니다. (그것은 C# 5이지만 .NET 4.5입니다.) –
@Jon 전혀 아님; 정말로 나를 고쳐 주셔서 감사합니다. –