我解释了我的情况。
我有一个生产者1到N的消费者模式。我正在使用阻塞集合,一切都运行良好。做一些测试我发现了这种奇怪的行为:
我正在测试我的数据处理对我的消费者的影响。 我注意到这些奇怪的东西,下面你会发现我的操作代码被清除了,并产生了奇怪的行为。
我有1位制作人的4位消费者。 对于大多数数据,控制台不打印任何东西,因为ts = 0(它在一个勾号下)但随机(在每1到5秒之间)它绘制这样的东西(不是按照这个非常特定的顺序,但是相同类型):
10000
20001
10000
30002
10000
40003
10000
10000
大约1个小时,大约是10,000个小时。始终为格式(N)000(N-1)的数字 请注意,我消耗的BlockingCollection是根据一些在随机时间完全发生的网络事件来填充的。这里没什么经常的。
时机几乎是完美的,总是10,000个刻度的倍数。
这背后可能是什么?谢谢!
while(IsAlive)
{
DataToFieldMapping item;
try
{
_CollectionToConsume.TryTake(out item, -1);
}
catch
{
item = null;
}
if (item != null)
{
long ts = (DateTime.Now.Ticks - item.TimeStamp.Ticks);
if(ts>10)
Console.WriteLine(ts);
}
}
答案 0 :(得分:4)
这里发生的事情是DateTime.Now
的精确度相当有限。它没有给你时间到最近的刻度线。它只会在每10,000个刻度左右更新一次,这就是为什么你通常会在打印件中看到10k刻度的倍数。
如果您真的想要更好地了解这些事件的持续时间,请使用StopWatch
类,它具有多更高的精度。也就是说,StopWatch
只是一个诊断工具(因此它在Diagnostics
命名空间中)。您应该只使用它来帮助您诊断正在发生的事情,并且应该在生产代码中使用它。
另一方面,根本没有必要在这里使用计时器。您似乎正在创建几个正在轮询BlockingCollection
新内容的消费者。没有理由这样做。他们可以简单地阻止,直到收集有物品。 (因此名称为BlockingCollection
。
最简单的方法是让消费者简单地这样做:
foreach(var item in _CollectionToConsume.GetConsumingEnumerable())
ProcessItem(item);
然后在后台线程中运行该代码。
答案 1 :(得分:1)
如果您编写以下内容并运行,您将看到刻度不会一对一滚动,而是相对较大的块b / c刻度分辨率实际上要小得多。
for(int i =0; i< 100; i++)
{
Console.WriteLine(DateTime.Now.Ticks);
}
使用Stopwatch
类测量性能,因为它使用了更适合此目的的高分辨率计时器。