如何取消等待Task.Delay()?

正如您在此代码中看到的:

public async void TaskDelayTest() { while (LoopCheck) { for (int i = 0; i < 100; i++) { textBox1.Text = i.ToString(); await Task.Delay(1000); } } } 

我希望它将文本框设置为一秒钟的字符串值,直到我将LoopCheck值设置为false 。 但它的作用是它为所有人创建了所有迭代的内容,即使我将LoopCheck值设置为false,它仍然会执行它异步执行的操作。

我想在设置LoopCheck=false时取消所有等待的Task.Delay()迭代。 我该如何取消?

使用Task.Delay的重载接受CancellationToken

 public async void TaskDelayTest(CancellationToken token) { while (LoopCheck) { for (int i = 0; i < 100; i++) { textBox1.Text = i.ToString(); await Task.Delay(1000, token); } } } ... var tokenSource = new CancellationTokenSource(); TaskDelayTest(tokenSource.Token); ... // cancelling LoopCheck = false; tokenSource.Cancel(); 

如果您要进行投票,请在CancellationToken上进行投票:

 public async Task TaskDelayTestAsync(CancellationToken token) { for (int i = 0; i < 100; i++) { textBox1.Text = i.ToString(); await Task.Delay(TimeSpan.FromSeconds(1), token); } } 

有关更多信息,请参阅取消文档 。

这可能是一个非常愚蠢和基本的解决方案,但我的想法是……

 public async void TaskDelayTest() { while (LoopCheck) { for (int i = 0; i < 100; i++) { textBox1.Text = i.ToString(); await Delay(1000); } } } private async void Delay(int delayInMillisecond) { for(int i=0; i 

这种方法的优点是您只需将LoopCheck设置为false即可实现您的目标,而其他方法则需要同时使用CancellationTokenSource.Cancel() 。 是的,这最多需要1毫秒来摆脱循环,但没有人能注意到这一点。

如果您希望延迟更准确,请尝试以下方法。

 public async void TaskDelayTest() { while (LoopCheck) { for (int i = 0; i < 100; i++) { textBox1.Text = i.ToString(); await Task.Run(()=>Delay(1000)); } } } private void Delay(int delayInMillisecond) { double delayInSec = (double) delayInMillisecond / 1000; var sw = new Stopwatch(); sw.Start(); while(true){ double ticks = sw.ElapsedTicks; double seconds = ticks / Stopwatch.Frequency; if(seconds >= delayInSec || !LoopCheck) break; } }