繁体   English   中英

线程和计时器的奇怪行为

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM