How to cancel await Task.Delay()?

后端 未结 4 755
生来不讨喜
生来不讨喜 2020-12-09 08:02

As you can see in this code:

public async void TaskDelayTest()
{
     while (LoopCheck)
     {
          for (int i = 0; i < 100; i++)
          {
                


        
相关标签:
4条回答
  • 2020-12-09 08:47

    Use the overload of Task.Delay which accepts a CancellationToken

    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();
    
    0 讨论(0)
  • 2020-12-09 08:47

    If you're going to poll, poll on a 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);
      }
    }
    

    For more information, see the cancellation documentation.

    0 讨论(0)
  • 2020-12-09 08:50

    Just a slight comment about having a cancellation token, and using a try-catch to stop it throwing an exception - your iteration block might fail due to a different reason, or it might fail due to a different task getting cancelled (e.g. from an http request timing out in a sub method), so to have the cancellation token not throw an exception you might want a bit more complicated catch block

    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
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-09 09:01
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static DateTime start;
            static CancellationTokenSource tokenSource;
            static void Main(string[] args)
            {
                start = DateTime.Now;
                Console.WriteLine(start);
    
    
                TaskDelayTest();
    
                TaskCancel();
    
                Console.ReadKey();
            }
    
            public static async void TaskCancel()
            {
                await Task.Delay(3000);
    
                tokenSource?.Cancel();
    
                DateTime end = DateTime.Now;
                Console.WriteLine(end);
                Console.WriteLine((end - start).TotalMilliseconds);
            }
    
            public static async void TaskDelayTest()
            {
                tokenSource = new CancellationTokenSource();
    
                try
                {
                    await Task.Delay(2000, tokenSource.Token);
                    DateTime end = DateTime.Now;
                    Console.WriteLine(end);
                    Console.WriteLine((end - start).TotalMilliseconds);
                }
                catch (TaskCanceledException ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    tokenSource.Dispose();
                    tokenSource = null;
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题