BlockingCollection.Add 到循环中并等待,花费的时间比预期要长得多

问题描述 投票:0回答:1

这里是我能做的最简单的重现来说明这个问题。这是一个控制台应用程序,它创建一个有界的

BlockingCollection<int>
,启动一个后台线程,使用
TryTake
消耗集合中的项目,然后在主线程上循环使用
Add
项目,直到达到上限,如下所示:

// Measure the time it takes to add items to the collection with one millisecond delay between Adds.
var sw = Stopwatch.StartNew();
for (int i = 0; i < collection.BoundedCapacity; i++)
{
  collection.Add(i);
  await Task.Delay(millisecondsDelay: 1); 
}
sw.Stop();

BoundedCapacity 为 1000 个项目,因此 for 循环花费的时间不应超过一秒。但是,正如示例代码中的注释所解释的那样,经过的时间始终大于最大预期时间(设置为 2 * BoundedCapacity 毫秒) - 在调试器下的我的机器上,时间在 3.2 范围内 - 4秒,而当运行没有调试器时,时间在15 - 16秒范围内!

当您注释掉行

await Task.Delay(millisecondsDelay: 1)
时,程序将按预期运行(循环将在几毫秒内完成)。

我不知道这里发生了什么。有人可以解释一下这种行为吗?

c# multithreading blockingcollection
1个回答
0
投票

我的猜测是这与操作系统调度有关。

文档 您可以了解到 Windows 上的最低分辨率窗口是 15 毫秒:

此方法取决于系统时钟。这意味着,如果 millisecondsDelay 参数小于系统时钟的分辨率(在 Windows 系统上约为 15 毫秒),则时间延迟将近似等于系统时钟的分辨率。

意味着对

Delay(1)
的 1000 次调用应该大约需要
15s
而不是
1s

© www.soinside.com 2019 - 2024. All rights reserved.