线程和计时器的奇怪行为

用户名

我解释我的情况。

我有一个生产者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);

然后,只需在后台线程中运行该代码即可。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章