C# 如何取消等待任务。延迟()?

C# 如何取消等待任务。延迟()?,c#,async-await,C#,Async Await,正如您在这段代码中看到的: public async void TaskDelayTest() { while (LoopCheck) { for (int i = 0; i < 100; i++) { textBox1.Text = i.ToString(); await Task.Delay(1000); } } } public异步v

正如您在这段代码中看到的:

public async void TaskDelayTest()
{
     while (LoopCheck)
     {
          for (int i = 0; i < 100; i++)
          {
               textBox1.Text = i.ToString();
               await Task.Delay(1000);
          }
     }
}
public异步void taskdaytest()
{
while(循环检查)
{
对于(int i=0;i<100;i++)
{
textBox1.Text=i.ToString();
等待任务。延迟(1000);
}
}
}
我希望它将textbox设置为
I
的字符串值,时间为1秒,直到我将
LoopCheck
值设置为
false
。但它所做的是在for all中创建所有迭代,即使我将LoopCheck值设置为false,它仍然异步执行它所做的操作

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

使用接受
取消令牌的
任务延迟

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

var tokenSource = new CancellationTokenSource();
TaskDelayTest(tokenSource.Token);
...
tokenSource.Cancel();
公共异步任务TaskDelayTest(CancellationToken令牌)
{
while(循环检查)
{
token.throwIfCancellationRequested();
对于(int i=0;i<100;i++)
{
textBox1.Text=i.ToString();
等待任务。延迟(1000,令牌);
}
}
}
var tokenSource=new CancellationTokenSource();
taskdaytest(tokenSource.Token);
...
tokenSource.Cancel();

如果您要进行投票,请使用
取消令牌进行投票

public async Task TaskDelayTestAsync(CancellationToken token)
{
  for (int i = 0; i < 100; i++)
  {
    textBox1.Text = i.ToString();
    await Task.Delay(TimeSpan.FromSeconds(1), token);
  }
}
公共异步任务TaskDelayTestAsync(CancellationToken令牌)
{
对于(int i=0;i<100;i++)
{
textBox1.Text=i.ToString();
等待任务延迟(TimeSpan.FromSeconds(1),令牌);
}
}

有关更多信息,请参阅。

关于使用取消令牌并使用try-catch阻止其引发异常的简短注释-您的迭代块可能由于不同的原因而失败,或者可能由于不同的任务被取消而失败(例如,由于子方法中的http请求超时),因此,要使取消令牌不引发异常,您可能需要更复杂的catch块

public async void TaskDelayTest(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        for (int i = 0; i < 100; i++)
        {
            try
            {
                textBox1.Text = i.ToString();
                await DoSomethingThatMightFail();
                await Task.Delay(1000, token);
            }
            catch (OperationCanceledException) when (token.IsCancellationRequested)
            {
                //task is cancelled, return or do something else
                return;
            }
            catch(Exception ex)
            {
                 //this is an actual error, log/throw/dostuff here
            }
        }
    }
}
public异步void taskdaytest(CancellationToken令牌)
{
而(!token.IsCancellationRequested)
{
对于(int i=0;i<100;i++)
{
尝试
{
textBox1.Text=i.ToString();
等待可能失败的事情发生();
等待任务。延迟(1000,令牌);
}
当(token.IsCancellationRequested)时捕获(OperationCanceledException)
{
//任务被取消,返回或执行其他操作
返回;
}
捕获(例外情况除外)
{
//这是一个实际的错误,这里是log/throw/dostuff
}
}
}
}

我建议查看取消代币。您不需要循环检查。您需要将令牌传递到方法中,并检查它是否在每次延迟后被取消。但正如你所承认的,关于这一点的报道是非常新的,而且还不够。也许这里有人知道如何使用CancellationToken事实上,这是一个非常详尽的方法,已经使用了将近四年了。它绝对有效。但现在还有另一个问题。当我取消任务时,我得到一个异常。我不能使用try-catch,因为如果我这样做,它会给出100次异常。现在怎么办?我知道我要求的太多了,但你似乎对这个主题非常了解。你需要决定取消任务时会发生什么,例如Try/Catch绕过延迟,在Catch中,你可以用“break”退出循环,或用“return”退出整个方法。当然,使用取消令牌,但是最简单的修复方法是合并while和for循环测试
对于(int i=0;i<100&&!token.IsCancellationRequested;i++)
@TheodorZoulias,您为什么不自己用另一种解决方案回答这个问题呢。它将允许您更详细地解释您的推理,例如“它可能随机抛出”不确定您的意思。如果条件
token.IsCancellationRequested
恰好为真,则方法将毫无例外地返回。如果在等待
Task.Delay
期间发生取消,则该方法将抛出。你无法判断哪一种情况会发生,因此存在随机性。我经常看到这种不一致,我认为这是一个缺点。嘿,欢迎。您的答案可能是正确的,但请尝试解释您的答案,而不是简单的代码转储:)此外,您可能希望捕获OperationCanceledException,因为您将捕获所有类型的已取消异常,而不仅仅是TaskCanceledException。
public async void TaskDelayTest(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        for (int i = 0; i < 100; i++)
        {
            try
            {
                textBox1.Text = i.ToString();
                await DoSomethingThatMightFail();
                await Task.Delay(1000, token);
            }
            catch (OperationCanceledException) when (token.IsCancellationRequested)
            {
                //task is cancelled, return or do something else
                return;
            }
            catch(Exception ex)
            {
                 //this is an actual error, log/throw/dostuff here
            }
        }
    }
}