[英]Strange Behavior with Threading and Timer
我解释我的情况。
我有一个生产者1到N的消费者模式。 我正在使用阻止收集,并且一切正常。 做一些测试,我注意到了这种奇怪的行为:
我正在测试对数据的处理花费了我的消费者多长时间。 我注意到了这些奇怪的事情,在下面您会发现清除了我的操作的代码,这些代码会产生奇怪的行为。
我有1个生产者的4个消费者。 对于大多数数据,控制台不打印任何内容,因为ts = 0(在刻度线下),但是随机(每1至5秒之间),它会绘制类似这样的内容(不是以这种非常特定的顺序,而是相同的种类) ):
10000
20001
10000
30002
10000
40003
10000
10000
它大约是10,000个滴答声,所以大约1毫秒。 始终为(N)000(N-1)格式的数字。请注意,我消耗的BlockingCollection是根据完全随机发生的某些网络事件填充的。 这里没有常规。
时机几乎是完美的,总是10,000刻度的倍数。
这可能是什么呢? ks!
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);
}
}
这里发生的是DateTime.Now
精度相当有限。 它没有给您时间到最近的滴答声。 它仅每10,000个刻度左右才更新一次,这就是为什么您通常在打印物中看到1万个刻度的倍数的原因。
如果你真的想获得这些事件的持续时间更好的手感,使用StopWatch
类,它具有更高的精度。 就是说, StopWatch
只是一个诊断工具(因此,它为什么位于Diagnostics
名称空间中)。 您应该仅使用它来帮助您诊断正在发生的事情,并且应该在生产代码中使用它。
顺便说一句,这里实际上根本不需要使用计时器。 看来您正在创建几个使用方,它们正在BlockingCollection
中轮询新内容。 没有理由这样做。 他们可以简单地阻止,直到集合中有项目为止。 (因此,名称为BlockingCollection
。
最简单的方法是让消费者简单地做到这一点:
foreach(var item in _CollectionToConsume.GetConsumingEnumerable())
ProcessItem(item);
然后,只需在后台线程中运行该代码即可。
如果编写以下代码并运行,您会发现刻度不会一一对应,而在相对较大的块中,b / c刻度的分辨率实际上要小得多。
for(int i =0; i< 100; i++)
{
Console.WriteLine(DateTime.Now.Ticks);
}
使用Stopwatch
类来衡量性能,因为它使用了更适合此目的的高分辨率计时器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.