C# ConcurrentQueue。在.NET Core中计数非常慢

C# ConcurrentQueue。在.NET Core中计数非常慢,c#,performance,.net-core,C#,Performance,.net Core,我正在使用ConcurrentQueue将I/O绑定任务中的项目排队,并将它们从另一个任务中排出以进行处理。当队列达到一定大小时,我会停止向队列中添加项目,以便处理能够赶上进度。为此,我检查ConcurrentQueue.Count属性 问题在于Count属性的行为与列表或其他集合中的行为不同。它非常慢,队列越大,读取Count属性的速度就越慢。ConcurrentQueue中有20k个项目几乎所有处理器时间都花在Count属性上 粗略示例: while (reader.Read

我正在使用
ConcurrentQueue
将I/O绑定任务中的项目排队,并将它们从另一个任务中排出以进行处理。当队列达到一定大小时,我会停止向队列中添加项目,以便处理能够赶上进度。为此,我检查
ConcurrentQueue.Count
属性

问题在于
Count
属性的行为与列表或其他集合中的行为不同。它非常慢,队列越大,读取
Count
属性的速度就越慢。
ConcurrentQueue中有20k个项目
几乎所有处理器时间都花在
Count
属性上

粗略示例:

        while (reader.Read())
        {
            if(Queue.Count >= MaxQueueSize)
            {
                //Wait
            }
            //Do Stuff
        }
运行性能分析器时,所有时间都花在
System.Collections.Concurrent.cdscollectionetwbclprovier.ctor()

这似乎只发生在.NET Core 2上,而在.NET 4.6.2中没有发生


在.Net Core中有什么方法可以解决这个问题吗?

由于现在两个框架的源代码都可用,因此可以查看两个
Count
版本的源代码。对于完整的.NET,它是,对于.NET核心,它是。你可以看到:

  • 这两个版本都很重要。它不像
    return\u count

  • .NET核心版本相当复杂,它包括缓慢的路径,其中整个队列被冻结只是为了计算稳定计数

  • 所以,.NET核心版本的速度通常较慢并不奇怪,但主要的一点是——这两个版本都很重要,在一个紧密的循环中使用它们不是一个好主意。除此之外,通过检查
    计数
    ,您就有了一个竞争条件,因为在您检查之后,另一个线程可能会立即更改它,所以不能保证队列在您的版本中包含小于max Count的值

    相反,请使用内置的容量受限集合,例如
    BlockingCollection

    var x = new BlockingCollection<string>(new ConcurrentQueue<string>(), MaxQueueSize);
    
    var x=new BlockingCollection(new ConcurrentQueue(),MaxQueueSize);
    
    你好,Evk,谢谢你提供的信息。这在.NET Framework上不是一个问题。仅在.NETCore上存在问题。您确定要获得
    计数
    需要访问所有项目吗?我将签出
    阻止收藏
    ,谢谢!当以FIFO方式接收项目时,这不会对性能产生严重影响?更新:阻止收集效果很好。如果你加上这个作为答案,我会接受的。可能是或的副本