0

언제 올지 Task.IsCanceled = true;Task.IsCancelled가 true로 설정되면?

코드 :

  var cts = new CancellationTokenSource(); 
      string result = ""; 
      cts.CancelAfter(10000); 
      try 
      { 
       Task t = Task.Run(() => 
       { 
        using (var stream = new WebClient().OpenRead("http://www.rediffmail.com")) 
        { 
         result = "success!"; 
        } 
        cts.Token.ThrowIfCancellationRequested(); 
       }, cts.Token); 

       Stopwatch timer = new Stopwatch(); 
       timer.Start(); 
       while (timer.IsRunning) 
       { 
        if (timer.ElapsedMilliseconds <= 10000) 
        { 
         if (result != ""){                      
          timer.Stop(); 
          Console.WriteLine(result); 
        } 
        } 
        else 
        { 
         timer.Stop(); 
         //cts.Cancel(); 
         //cts.Token.ThrowIfCancellationRequested(); 
        } 
       } 
      } 
      catch (OperationCanceledException) 
      { 
       Console.WriteLine(t.IsCanceled); // still its appear in false. 
      } 

내 요구 사항입니다 - 작업은 작업을 취소 할 필요가 십초 개까지 완료되지 않습니다.

그래서 타이머를 설정하고 주어진 초까지 볼 수 있습니다. 완료되지 않았 으면 작업을 취소하고 오류 메시지를 표시합니다. 문서에서

+3

[최소, 완료 및 확인 가능한 예제] (http://stackoverflow.com/help/mcve)를 포함하십시오. 당신이 보여주는 것은 불완전합니다. – Igor

+1

토큰을 취소하는 것만으로는 충분하지 않습니다. 작업 취소를위한'method' 코드를 확인해야합니다. – VMAtm

+1

작업 t가 기다리는 코드를 표시 할 수 있습니까? 그리고 올바른 방법으로 실행하는 데 20 초 이상 걸리면 전체 작업을 취소하고 싶습니까? –

답변

1

:

작업이 다음 조건 하에서 TaskStatus.Canceled 상태에 완료 : 작업이 실행을 시작하기 전에

  1. 그 CancellationToken은 취소 표시했다.

  2. 작업은 동일한 CancellationToken을 지닌 OperationCanceledException을 던져서 이미 신호 화 된 CancellationToken에 대한 취소 요청을 확인했습니다.

  3. 이 작업은 CancellationToken에서 ThrowIfCancellationRequested 메서드를 호출하여 이미 신호 화 된 CancellationToken에 대한 취소 요청을 확인했습니다.

그래서 기본적으로 당신은 당신이 그것을 취소 직후 cts.Token.ThrowIfCancellationRequested()을 실행하여 작업 내에서 OperationCanceledException이 인스턴스의 상태를 강제로 던져해야합니다.

하지만이 메커니즘의 의도는 다른 점입니다. 당신은 코드의 포인트를 취소하기 위해 일부 저장에서 취소가 요청되었는지를 사용자가 확인한 후에 작업이 사용자의 양식에서 취소 버튼을 누르는 동안 소스가 취소된다고 말합니다.

2

메서드에 토큰을 전달해야합니다. 토큰을 검사하고 CancellationTokenSourceCancel()에 대한 호출을 존중해야합니다.

아니면 스스로를 수행

Task t = Task.Factory.StartNew(() => 
{ 
    myResult = method(); // Request processing in parallel 

    cts.Token.ThrowIfCancellationRequested(); // React on cancellation 
}, cts.Token); 

완전한 예는 이것이다 :

async Task Main() 
{ 
    var cts = new CancellationTokenSource(); 
    var ct = cts.Token; 
    cts.CancelAfter(500); 

    Task t = null; 
    try 
    { 
     t = Task.Run(() => { Thread.Sleep(1000); ct.ThrowIfCancellationRequested(); }, ct); 
     await t; 
     Console.WriteLine(t.IsCanceled); 
    } 
    catch (OperationCanceledException) 
    { 
     Console.WriteLine(t.IsCanceled); 
    } 
} 

출력은 OperationCanceledException이 발생된다는 것이다 결과는

True입니다

당신이 ct.ThrowIfCancellationRequested(); 부분을 제거하면

그것은

거짓

편집을 표시합니다 :

지금, 당신은 질문이에 대한 몇 가지 의견을 업데이트했습니다. 먼저 CancelAfter 메서드를 사용하고 있으므로 타이머가 더 이상 필요하지 않습니다. 둘째, await 작업이 필요합니다. 그래서 이런 식으로 뭔가를 만들어 :

string result = ""; 
cts.CancelAfter(10000); 
Task t = null; 
try 
{ 
    t = Task.Run(() => 
    { 
     using (var stream = new WebClient().OpenRead("http://www.rediffmail.com")) 
     { 
      cts.Token.ThrowIfCancellationRequested(); 
      result = "success!"; 
     } 
    }, cts.Token); 

    await t; 
} 
catch (OperationCanceledException) 
{ 
    Console.WriteLine(t.IsCanceled); 
} 

t.IsCanceledtrue하지만 물론 WebClient의 호출이 더 이상 그 10 초 걸리는 경우에만 있음을 보여 주어야한다.

+0

작업 t = Task.Factory.StartNew (() => { myResult = method(); // 병렬 처리 요청 처리 }, cts.Token); // 얼마 후 cts.cancel cts.Token.ThrowIfCancellationRequested(); 가능 여부 없습니까? 여기 t.iscancelled 결코 사실로 온다. –

+0

작업 t가 기다리는 코드를 표시 할 수 있습니까? 그리고 올바른 방법으로 실행하는 데 20 초 이상 걸리면 전체 작업을 취소하고 싶습니까? –

+0

코드를 공유하는 방법은 무엇입니까? 여기에 너무 긴 등장 인물이 있습니다. –