2017-08-28 26 views
0

我有一個應用程序,其中一部分代碼以定時器延遲的循環運行。如何停止在while循環中運行的運行計時器?

在應用程序的開始,我宣佈:

public static CancellationTokenSource tokenSource1 = new CancellationTokenSource(); 
public static bool Timer1Running; 

這裏的循環區域:

while (App.runCardTimer && App.TimerSeconds > 0) 
{ 
    App.Timer1Running = true;  
    … 
    await Task.Delay(1000, App.tokenSource1.Token); 
    App.TimerSeconds--;  
    App.Timer1Running = false;  
} 

我的應用程序響應在屏幕上點擊這樣的:

wordGrid.GestureRecognizers.Add(  
    new TapGestureRecognizer()  
    {   
     Command = new Command(() =>   
     {   
     App.TimerSeconds = 0;   
     if (App.tokenSource1 != null && App.Timer1Running)   
     {    
      App.tokenSource1.Cancel();   
     }  
     })  
    }); 

當它運行並且點擊屏幕時,它會到達代碼 App.tokenSource1.Cancel()

然而,它似乎停止。

有沒有人有任何想法我可能做錯了。我曾希望代碼立即去到線路App.TimerSeconds--;,並沒有想到它會在此之前停下來。

+1

但你已經設置App.TimerSeconds = 0,所以肯定是趁現在不再運行,因爲它依賴於App.TimerSeconds> 0? –

+0

如果您想要定時器,請使用定時器。「await Task.Delay」在取消時引發TaskCanceledException –

+0

。如果你[檢查源代碼](https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,5896),你會看到'Task.Delay'本身使用一個定時器來設置TaskCompletionSource的完成狀態。 –

回答

1

await Task.Delay(1000, App.tokenSource1.Token);
拋出System.Threading.Tasks.TaskCanceledException取消時。
所以,你需要將它包裝在try-catch代碼:

{ 
    App.Timer1Running = true;  
    … 
    try 
    { 
     await Task.Delay(1000, App.tokenSource1.Token); 
    } 
    catch(TaskCanceledException ex){} 
    App.TimerSeconds--;  
    App.Timer1Running = false;  
} 
+0

謝謝。順便一提。一旦我創建了一個新的tokenSource1,我可以反覆使用它嗎? – Alan2

+0

您可以使用它多次獲取令牌並在許多操作中使用它們。但是一旦CancellationTokenSource被取消,您從它獲取的所有令牌也將取消,並且CancellationTokenSource本身將永久轉換爲取消狀態。 –