2016-09-23 6 views
0

나는 (내 눈에서) 이상한 행동을 이해하려고합니다. 일부 비동기 메서드에 대한 호출이 있고 해당 결과를 검색하려고합니다. 이 시나리오 Result에서Task.ContinueWith() 이해하려고 시도합니다.

var deleteTask = Task.Run(() => DeleteIndexAsync(localItem)) 
    .ContinueWith(t => 
    { 
    //handle and log exceptions  
    }, TaskContinuationOptions.OnlyOnFaulted); 

if (!deleteTask.Result) 

(A Task<bool>을 반환 DeleteIndexAsync은) false하고 StatusWaitingForActivation입니다. 이 코드 반면

내가

var deleteTask = Task.Run(() => DeleteIndexAsync(localItem)); 
    deleteTask.ContinueWith(t => 
    { 
    //handle and log exceptions 
    return false; 
    }, TaskContinuationOptions.OnlyOnFaulted); 

    if (!deleteTask.Result) 

누군가가 이유를 설명 할 수 원하는 것을? 그리고 여기서 Task 대신 async/await을 사용할 수 있습니까?

편집 : 첫 번째 예에서와 같이 통화를, 체인 경우

var deleteTask = Task.Run(() => ThrowEx()); 
    bool errorOccurred = false; 
    deleteTask.ContinueWith(t => 
    {   
    errorOccurred = true; 
    }, TaskContinuationOptions.OnlyOnFaulted); 

    if (errorOccurred) 
    { 
    return true; 
    } 

답변

2

, 당신은 deleteTask 변수에 할당하는 값이 실제로 두 번째 Task입니다. 이 작업은 첫 번째 작업 (하나는 DeleteIndexAsync)의 실패시에만 실행되어야합니다.

Task.RunTask.ContinueWith이 모두 Task으로 반환되기 때문입니다. 첫 번째 예제에서 Status == WaitingForActivation을 얻는 이유를 설명합니다. 첫 번째 스 니펫에서 deleteTask.Result에 액세스하면 예외가 발생합니다. DeleteIndexAsync이 던져 넣은 경우 t.Exception에 액세스하지 않는 한 원래 예외가 포함 된 AggregateException이됩니다. 그렇지 않으면 "작업이 취소되었습니다"라는 메시지가 나타납니다. 이는 조건부로 예약 된 작업의 결과를 얻으려고하기 때문입니다. 조건이 충족되지 않았습니다. 당신이이 냈다 포함하는 방법을 한 경우

async 당신은 (테스트하지)과 같이 그것을 할 수 :

bool success = false; 
try 
{ 
    success = await DeleteIndexAsync(localItem); 
} 
catch (Exception) {} 

if (!success) 
{ 
    //TODO: handler 
} 

을 질문 편집에 관한 :

도움이 캡처 된 변수를 사용하지만, 현재 솔루션 경쟁 조건을 도입합니다.

var deleteTask = Task.Run(() => ThrowEx());  

try 
{ 
    deleteTask.Wait(); 
} 
catch (Exception ex) 
{ 
    return true; 
} 

을하지만 당신은 즉시 결과를 기다려야하기 때문에이 시점에서 당신은 완전히 비동기 호출을 삭제할 수 있습니다 -이 예 Run 사이에 할 수있는 일을 단순화되지 아니하는 한,이 경우에는 다음과 같이 할 더 좋을 것이다 및 Wait)

+0

나는 task.Result가 오류가 발생했는지 여부를 확인하는 것이 좋다고 생각하지 않는다. task.Result에 액세스하면 여기에 예외가 발생하고 예외가 throw 된 경우에도 Faulted 플래그는 항상 false입니다. – user3292642

+0

@ user3292642 내가 이해할 것 같지 않니? 예외를 삼키려면'Exception' 속성에 접근해야합니다. – slawekwin

+0

예외를 삼키고 싶지 않습니다. 나는 이미 그것을 continuewith 방법으로 기록하고있다. 로깅이 완료된 후 예외가 발생하면 반환하고 싶지만 어떻게 처리되는지는 알 수 없습니다. 상태를 점검하는 것도 옵션이 아닙니다. – user3292642

2

일부 비동기 메서드가 호출되어 결과를 검색하려고합니다.

The best way to do this is with await, not Result.

누군가가 이유를 설명 할 수 있습니까?

첫 번째 예에서 deleteTaskTask.Run에서 반환 된 작업입니다. 두 번째 예에서 deleteTaskContinueWith에서 반환 된 작업입니다.DeleteIndexAsync이 예외를 throw하지 않는 한이 작업은 실제로 실행되지 않습니다.

여기서 Task 대신 async/await를 사용할 수 있습니까?

네, 그게 최선의 방법입니다. 비동기 코드로 작업 할 때는 항상 use await instead of ContinueWith이어야합니다. 이 경우, TaskContinuationOptions.OnlyOnFaulted 당신이 awaitcatch 블록의 연속 코드를 삽입해야 의미 DeleteIndexAsync가 비동기 것 같습니다 이후,

bool deleteResult; 
try 
{ 
    deleteResult = await Task.Run(() => DeleteIndexAsync(localItem)); 
} 
catch (Exception ex) 
{ 
    //handle and log exceptions 
} 
if (!deleteResult) 
    ... 

또는 Task.Run을 제거하는 것이 더 적절할 것 :

bool deleteResult; 
try 
{ 
    deleteResult = await DeleteIndexAsync(localItem); 
} 
catch (Exception ex) 
{ 
    //handle and log exceptions 
} 
if (!deleteResult) 
    ... 
관련 문제