2017-12-25 12 views
0

나는이 코드를 가지고 있으며 CancellationToken의 사용에 대한 설명을하고 싶습니다.CancellationToken을 취소하면 CancellationToken 예외가 발생합니까?

나는 토큰 및 플래그 취소를 사용 사이의 차이에 대한이 질문을 읽어 눈치

Difference between CancellationTokenSource and exit flag for Task loop exit

한 가지가 예외에 대해 아무것도 언급하지 않는다는 것이다. 그래서 여기에 내 질문이있다. Disappearing() 메서드가 호출되면 TaskCanceledException()이 발생하게되고 이것이 플래그 대신 CancellationToken을 사용하는 좋은 이유가됩니까? 그 자체로

public partial class PhrasesFrame : Frame 
{ 
    CancellationTokenSource cts = new CancellationTokenSource(); 

    public PhrasesFrame(PhrasesPage phrasesPage) 
    { 
     Device.BeginInvokeOnMainThread(() => ShowCards(cts.Token).ContinueWith((arg) => { })); 
    } 

    public void Disappearing() 
    { 
     cts.Cancel(); 
    } 

    public async Task ShowCards(CancellationToken ct) 
    { 
     while (!ct.IsCancellationRequested) 
     { 
      await PickCard(); 
     } 
    } 

    public async Task PickCard() 
    { 
     await ShowCard(); 
    } 

    private async Task ShowCard() 
    { 
     await ShowPhrase(); 
     await ShowDetail(); 
    } 

    private async Task ShowPhrase() 
    { 
     while (App.pauseCard || timer1Seconds > 0) 
     { 
      try 
      { 
       await Task.Delay(1000, tokenSource1.Token); 
      } 
      catch (TaskCanceledException) 
      { 
       // do action 
       break; 
      } 
     } 
+3

당신은 문서 [CancellationToken.ThrowIfCancellationRequested] (https://msdn.microsoft.com/library/system.threading.cancellationtoken.throwifcancellationrequested (V = vs.110을)에서 .aspx) 예약비 CancellationToken –

+1

을 취소 할 수 없습니다 –

답변

1

CancellationTokenSource.Cancel는 예외를 발생하지만, "이동"취소 된 상태로 모든 관련 취소 토큰하지 않습니다. 일부 코드에서 취소 토큰이 취소 된 상태임을 알릴 때 - 일 수 있습니다. 예외가 발생합니다. 예를 보면,이 부분은 예외를 throw하지 않습니다.

public async Task ShowCards(CancellationToken ct) 
{ 
    while (!ct.IsCancellationRequested) 
    { 
     await PickCard(); 
    } 
} 

이 블록에 버리지 않기 때문입니다. 그러나 대신 다음과 같이하면 :

public async Task ShowCards(CancellationToken ct) 
{ 
    while (true) 
    { 
     ct.ThrowIfCancellationRequested(); 
     await PickCard(); 
    } 
} 

그렇다면 잘 던지기 때문에 예외가 throw됩니다.

이제 경우 귀하의 예제에서 다른 방법을 봐 : 당신이 Task.Delay(1000, tokenSource1.Token);을 기다리고 다음 tokenSource1 취소 된 경우

private async Task ShowPhrase() 
{ 
    while (App.pauseCard || timer1Seconds > 0) 
    { 
     try 
     { 
      await Task.Delay(1000, tokenSource1.Token); 
     } 
     catch (TaskCanceledException) 
     { 
      // do action 
      break; 
     } 
    } 
} 

- 다음 TaskCancelledException 실제로 Task.Delay의 전체 기간을 기다리지 않고 즉시 발생합니다. 이는 부울 플래그로 쉽게 달성 할 수없는 것입니다. Thread.Sleep(1000)을 사용하고 부울 플래그 - 해당 플래그로 변경하면 모든 수면 시간이 끝날 때까지 알리지 않습니다.

질문에 답하기 : CancellationTokenSource을 취소하는 순간 현재 실행중인 코드 부분에 따라 예외 예외가 발생할 수도 있고 그렇지 않을 수도 있습니다. (나는 cts이라는 이름의 두 취소 토큰 소스를 사용하고 있다고 가정합니다. tokenSource1은 코드의 오타에 지나지 않지만 실제 코드 인 경우 cts을 취소하지만 대기 코드는 tokenSource1이므로 취소 할 수 없습니다.