首页 > 解决方案 > 为什么取消 Task.Delay 很慢?

问题描述

我创建了一个运行 1000 个任务的测试程序,这些任务Task.Delay以 20 秒到 30 秒之间的随机延迟执行。取消此操作似乎需要大约 10 秒..

这是我的测试程序:

class Program
{
    static async Task MainAsync()
    {
        CancellationTokenSource tokenSource = new CancellationTokenSource();

        List<Task> allTask = new List<Task>();
        Random r = new Random(9);

        async Task SafeDelay(int delay, CancellationToken token)
        {
            try
            {
                await Task.Delay(delay, token);
            }
            catch (TaskCanceledException)
            {
            }
        }

        for (int i = 0; i < 1000; i++)
        {
            var randomDelay = r.Next(20000, 30000);
            allTask.Add(SafeDelay(randomDelay, tokenSource.Token));
            ;
        }

        Stopwatch stopwatch = new Stopwatch();

        var cancelTask = Task.Delay(1000).ContinueWith(t =>
        {
            Console.Out.WriteLine("1000ms elapsed. Cancelation request start");;
            stopwatch.Start();
            tokenSource.Cancel();
        });

        await Task.WhenAll(allTask);
        await cancelTask;

        stopwatch.Stop();

        Console.WriteLine($"Cancelation done after {stopwatch.ElapsedMilliseconds} ms");
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Started");
        Task.Run(MainAsync).GetAwaiter().GetResult();
        Console.WriteLine("End");
        Console.ReadLine();
    }
}

我使用 .NET Core 2.1 的结果:

Cancelation done after 9808ms

为什么取消 Task.Delay 这么慢,有没有办法改进它?

我使用 .NET 4.7.1 的结果:

Cancelation done after 6200ms

标签: c#asynchronous

解决方案


当我运行它时,F5我得到了类似的结果。使用+ (无调试器)
运行它,它会在 50 毫秒内取消。CtrlF5

因此,您实际上是在为调试器计时 1000 次执行。调试器也可能干扰其他执行点。始终在发布模式下运行基准测试,不带调试器。


推荐阅读