2012-05-12 6 views
7

을 취소 내가 가지고있는 TPL 활용하여 내 코드에서 다음과 같은 설정 : 내 수업에서TPL 취소 계속 작업

  • 한 필드 : 개인 CancellationTokenSource _cancellationTokenSource을;
  • 이 CancellationTokeSource는 사용 나는 TPL 작업을 만들 때마다 특정 cancellationtoken 것을

가 actualy TPL 작업은 다음과 같이 instatiated됩니다 :

이제
var dataRetrievalTask = new Task<List<myType>>(() => 
      { 
       // retrieve data and do something 
       foreach (var a in retrievalMethod()) 
       { 
        if (_cancellationTokenSource.Token.IsCancellationRequested) 
         _cancellationTokenSource.Token.ThrowIfCancellationRequested(); 

         // do something if not cancelled 
        } 
       } 

       return filledListOfMyType; 

      }, _cancellationTokenSource.Token); 

      // define what shall happen if data retrievel finished without any problems 
      var writingLoadedDataToGridTask = dataRetrievalTask.ContinueWith(task => 
      { 
       // do something in case we ran to completion without error 
      }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, currentScheduler); 

      // what to do in case cancellation was performed 
      var loadingDataCancelledTask = dataRetrievalTask.ContinueWith(task => 
           { 
           someLabel.Text = "Data retrieval canceled."; 
           },_cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnCanceled, currentScheduler); 

      // what to do in case an exception/error occured 
      var loadingDataFaulted = dataRetrievalTask.ContinueWith(task => 
       { 
        someLabel.Text = string.Format("Data retrieval ended with an Error."); 
       }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, currentScheduler); 

      // when any of the continuation tasks ran through, reset ui controls/buttons etc 
      Task.Factory.ContinueWhenAny(new[] { writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted }, task => 
      { 
       // reset controls and all that 
      }, _cancellationTokenSource.Token, TaskContinuationOptions.None, currentScheduler); 


      dataRetrievalTask.Start(); 

내 문제는이 때 _cancellationTokenSource.Cancel 그() 메서드는 특정 loadingDataCancelledTask의 본문/메서드가 호출되지 않는 어딘가에 (Cancel- 단추의 .Click 이벤트 처리기에서) 호출됩니다.

내가 뭘 잘못하고 있니? 동일한 _cancellationTokenSource.Token 인스턴스를 사용하고 전달하는 중입니다. 다른 모든 작업 ('writingLoadedDataToGridTask'및 'loadingDataFaulted'작업 & 다음 'Task.Factory.ContinueWhenAny (new [] {writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted}) 작업 => ... '블록) 실제로 작동 않습니다. 만 취소가되지 않습니다. 아는 사람/참조 않는 이유는 무엇입니까?

답변

8

가 동일한 취소 토큰을 사용하기 때문에 귀하의 취소 계속 취소되고있다.

당신이 생각하는 경우 "모든 처리를 취소하고 싶다"고 말하면 실제로 요청한 것을 얻습니다. UI 업데이트를 포함하여 모든 처리가 중지됩니다.

해결책은 취소, 오류 및 ContinueWhenAny 계속에 대해 취소 토큰을 사용하지 않는 것입니다. 그런 식으로 이러한 연속은 항상 실행됩니다.

+1

오, 내 말은, 네가 말한대로 말이야. 고마워! –

+0

그래서 'TaskContinuationOptions.OnlyOnCanceled'는 무엇을 의미합니까 ??? 도망 갈 수 없어? – Jasper

+0

* 기본 작업 *이 취소 될 때 실행된다는 의미입니다. 그러나 당신은 선택적으로 연속을 취소 할 수 있습니다. 원하지 않으면 취소 토큰을 전달하지 마십시오. – usr