2017-08-28 82 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本身将永久转换为取消状态。 –