首页 > 解决方案 > VS2019-Debugger 产生高 CPU(取决于 CancellationTokens?)

问题描述

我们正在创建一个包含生产者-消费者问题的应用程序。有 100 多个消费者被告知价值。每个消费者在 a 中运行Task.Run并正在检查 aCancellationToken以取消它的工作。

如果此应用程序在 VS2019(16.5.4 最新版本)调试器中运行,则会产生高 CPU 使用率。从正在运行的应用程序中分离调试器后,CPU 使用率下降到预期值。

我能够将问题简化为这段代码:

private static void Main(string[] args)
{
    Console.WriteLine("Press to start...");
    Console.ReadKey();

    var cts = new CancellationTokenSource();
    var cancellationToken = cts.Token;

    var buffers = (from _ in Enumerable.Range(0, 40)
                   let queueLock = new SemaphoreSlim(1)
                   let queue = new ConcurrentQueue<object>()
                   select (queueLock, queue)).ToList();

    async Task Producer()
    {
        var instance = new object();

        var loop = 0;
        while (!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(10, cancellationToken);
            foreach (var (queueLock, queue) in buffers)
            {
                queue.Enqueue(instance);
                queueLock.Release();
            }

            ++loop;
            if (loop % 100 == 0)
                Console.WriteLine(loop);
        }
    }

    async Task Consumer(SemaphoreSlim queueLock, ConcurrentQueue<object> queue)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await queueLock.WaitAsync(cancellationToken);
            queue.TryDequeue(out _);
        }
    }

    foreach (var (queueLock, queue) in buffers)
    {
        Task.Run(() => Consumer(queueLock, queue), CancellationToken.None);
    }

    Task.Run(Producer, CancellationToken.None);

    Console.ReadKey();
    cts.Cancel();
}

下图显示了该行为。该过程在任务管理器中突出显示。

在此处输入图像描述

有趣的是,如果将行更改var cancellationToken = cts.Tokenvar cancellationToken = CancellationToken.None. 如果将SemaphoreSlimand替换ConcurrentQueue<T>为 a ,问题就完全消失了BlockingCollection<T>。但这不是一个选项,因为如果没有产生值,这会阻塞 ThreadPool 中的所有线程。

在我们使用的生产代码中AsyncCollection<T>,这会导致同样的问题。在这种情况下,我们不需要 aSemaphoreSlim但排除我使用的这个集合 aSemaphoreSlimConcurrentQueue<T>确保只使用本机提供的类型。

是什么导致了这种 CPU 使用率?如何避免?

我需要担心吗?

我们试图禁用 VS 的诊断,但这并不能解决问题。

提前致谢。

该代码是使用 VS 2019 (16.5.4) 针对 .Net Framework 4.7.2 编译的。

更新

在 Blindy 的提示之后,我向 github roslyn 报告了这个问题: https ://github.com/dotnet/roslyn/issues/44009

目前它被认为是一个错误。

++更新

我尝试了频道,但问题仍然存在。

标签: c#debuggingasync-awaitcpu-usagecancellation-token

解决方案


推荐阅读