2014-09-18 6 views
4

ContinuationOption.AttachedToParent 플래그에 문제가 있습니다. 내가 아는TPL 계속 작업 : 누가 상위 작업인지 확실하지 않음

Task parentTask = Task.Start(() => 
    { 
     Task childTask = Task.Start(() => doSomething(), 
            ContinuationOption.AttachedToParent); 
     childTask.ContinueWith(() => followingMethod(), 
            ContinuationOption.AttachedToParent); 
    } 

"해봐요()가"던져 예외 childTask이 실패하고 parentTask도 실패 할 경우 ContinuationOption.AttachedToParent 옵션 이유는

이 내 의사 코드이다.

followingMethod()가 예외를 throw하지만 parentTask 상태가 Completed 인 경우 동일한 동작이 발생할 것으로 예상됩니다.

내가 잘못했거나 계속 작업의 "부모"작업이 내 "parentTask"가 아닙니까?

답변

0

이 컨텍스트의 상위 타스크는 안에과 같이 내에서 Task.Factory.StartNew과 같은 하위 타스크를 작성한 것입니다.

자식 작업 (또는 중첩 된 작업)은 부모 작업이라고하는 다른 작업의 사용자 대리인에서 만들어진 System.Threading.Tasks.Task 인스턴스입니다. 하위 작업은 분리되거나 첨부 될 수 있습니다. 분리 된 하위 타스크는 상위와 독립적으로 실행되는 타스크입니다. 첨부 된 하위 작업은 TaskCreationOptions.AttachedToParent 옵션을 사용하여 만든 중첩 된 작업입니다.

Attached and Detached Child Tasks

당신이 작업에 계속 등록

는, 그 작업은 선행 작업이 아닌 부모입니다. ContinueWith으로 전화하면 작업이 다시 진행됩니다. 이것은 예외를 확인하는 데 필요한 작업입니다.

var continuation = task.ContinueWith(() => followingMethod()); 
+0

나는 childTask가 continuationTask의 전제이며 그것이 내가 원하는 "체인"이라는 것을 알고있다. 무엇이 나를 괴롭히는 사실은 continuationTask가 실패 할 경우 parentTask가 실패하지 않는다는 것입니다. 반면 childTask가 실패하면 부모 태스크도 실패합니다. 두 번째 세대 태스크는 모두 두 번째 태스크가 Attached로 표시된 경우 동일한 방식으로 내 1 세대 태스크에 영향을 주어야합니다. – SteBert

+0

@ user3798930 글쎄, .Net의 디자이너들은 분명히 의견이 맞지 않습니다.귀하의 경우에는'childTask'는 결코 부모가 아닙니다. 연속은 parentTask 인 부모에게 연결될 것입니다. – i3arnon

+0

나는 그가 그 childTask가 부모가되어야한다는 것을 암시했다고 생각하지 않는다. 연속 작업은 선행 (childTask)과 상위 (parentTask)를 모두 가질 수 있으며 첨부 된 하위 작업의 예외는 선행 작업과 관계없이 상위 작업으로 다시 전파됩니다. –

1

직감이 정확하지만 잘못된 API를 사용했을 가능성이 가장 높습니다.

나는 단지 의사 코드라는 것을 알고 있지만 Task.Start()은 정적 메서드가 아니라 인스턴스 메서드이므로 사용자가 지정한 방식대로 컴파일되지 않으며 실제로 어떻게 시작하는지 알지 못합니다. 작업 및 세부 사항이 중요합니다. TaskFactory.StartNew은 원하는대로 처리하지만 Task.Run은 처리하지 않습니다. 이 시도 :

Task parent = Task.Factory.StartNew(() => 
{ 
    Task child = Task.Factory.StartNew(
    () => { Console.WriteLine("foo"); }, 
    TaskCreationOptions.AttachedToParent); 
    Task continuation = child.ContinueWith(
    (Task prev) => { throw new InvalidOperationException("Test"); }, 
    TaskContinuationOptions.AttachedToParent); 
}); 
try 
{ 
    parent.Wait(); 
} 
catch (AggregateException ex) 
{ 
    if (ex.Flatten().InnerException is InvalidOperationException) 
    { 
    Console.WriteLine("The continuation exception was propagated to parent"); 
    } 
} 

당신이

Task parent = Task.Factory.StartNew(...) 

Task parent = Task.Run(...) 

다음 원하는 행동을받지 않습니다 변경하는 경우, Task.RunTaskFactory.StartNew 그 (다른 사이의 래퍼가 기본적으로 있기 때문에 things)는 TaskCreationOptions.DenyChildAttach으로 지정되므로 두 중첩 된 작업이 모두 분리되어 실행됩니다 (부모가없는 경우). 그게 네 문제였던 것 같아.

+0

'StartNew'는 명시 적 작업 스케줄러와 함께 사용해야합니다. – VMAtm