2014-02-12 1 views
2

나는이 패턴을 사용할 수있는 것으로 예상 처리하지 않습니다기다려온 작업이 예외가 정상적으로

내 SQL 서버가 시작되지
var task = Task.Run(() => Agent.GetUserType(Instance)); 
await task; 
string information = task.GetExceptionOrStatus(); // extension method 

- 단지 테스트 케이스로 - 나는 예외가 WCF 서비스가 발생한다는 것을 알,
'System.ServiceModel.FaultException'유형의 예외가 Microsoft.Threading.Tasks.dll에서 발생했지만 사용자 코드에서 처리되지 않았습니다.
나는 내 코드가 작업 객체에서 오류를 추출 할 수 있다는 인상하에 있었다.

어떻게하면 좋을까요?

답변

5

await은 의도적으로 해당 작업에 대한 예외를 전파합니다.

var task = Task.Run(() => Agent.GetUserType(Instance)); 
try 
{ 
    await task; 
} 
catch (Exception ex) 
{ 
    // TODO 
} 
string information = task.GetExceptionOrStatus(); // extension method 
+0

.net 4.5에서'ThrowUnobservedTaskExceptions'를 비활성화 할 때 try-catch없이 수행 할 수 있습니까? – Gerard

+2

@Gerard :'ThrowUnobservedTaskExceptions'는이 동작과 관련이 없습니다. 예외를 전파하는 것은'async'가 설계된 방식이었습니다. 당신이 * 원하지 않는 이유가 있습니까? –

+0

try-catch없이 작업 결과에 쉽게 액세스 할 수 있습니다. 예 : 'InotifyTaskCompletion'은'ContinueWith'와'PropertyChanged' 콜백을 통해 예외를 우아하게 처리합니다. 아마도'task.Exception.Handle'을 조사해야 할 것입니다. 반면에 try-catch는 명시 적이며 또한 좋은 것입니다. – Gerard

1

await task;을 try/catch 블록으로 묶어야합니다. Exception이 발생하면 Task에서 발생한 모든 예외가 포함 된 AggregateException가 표시됩니다.

+1

가 기다려온 작업이 실제로있을 것이다 그 AggregateException '미개봉'당신은 그것을 기다리고 있습니다 때. 태스크가 FormatException으로 실패하면 FormatException을 직접 catch 할 수 있습니다. –

+0

정말요? 나는 기다렸던 메소드에 대해 예외를 잡을 때마다'AggregateException'을 보았다. 어쩌면 내가 잘못 생각하고있다 ... –

+1

'Task.Wait' 또는'Task.Result'는 AggregateException을 던질 것이지만, 기다리는 것은 그렇지 않을 것이다. 사실 AggregateException에 여러 예외가 있더라도 첫 번째 예외 만 throw합니다. 기본 집계 예외를 가져 오려면 예외가 발생한 직후에 작업에서 쿼리를 쿼리해야합니다. 자세한 내용은 [이 질문] (http://stackoverflow.com/questions/18314961/i-want-await-to-throw-aggregateexception-not-just-the-first-exception)을 참조하십시오. –

2

당신이 던져 await을 원하지 않는 경우, 이전 Task 기반으로 새 Task, 그건 결코 실패하지 않는다 만들 수 있습니다.

static async Task<T> IgnoreException<T>(this Task<T> task) 
{ 
    try 
    { 
     return await task; 
    } 
    catch 
    { 
     return default(T); 
    } 
} 

대체 구현 : 뭐 그런 다음

static Task<T> IgnoreException<T>(this Task<T> task) 
{ 
    return task.ContinueWith(t => t.Exception == null ? t.Result : default(T)); 
} 

사용법은 다음과 같이 보일 것이다 :

await task.IgnoreException(); 
string information = task.GetExceptionOrStatus(); // extension method 
+0

어쩌면 ..이 방법을 사용합니까? Stephan Cleary는 일종의'On Error Resume Next'와 비교합니다. – Gerard

+0

@ 제라드 나는 조심 스러울 것이다. 이름에서 알 수 있듯이 항상 예외를 읽는'GetExceptionOrStatus()'를 항상 따라 다니고 있다면 괜찮다고 생각합니다. – svick

관련 문제