Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 定时器刚刚赢了';不要死(已经死了!)_C# - Fatal编程技术网

C# 定时器刚刚赢了';不要死(已经死了!)

C# 定时器刚刚赢了';不要死(已经死了!),c#,C#,一段时间以来,我一直在经历这种反复出现的噩梦(我的应用程序中存在读取错误)。出于某种原因,某个计时器在我停止后继续发送“已用”事件,即使事件本身中的计时器“承认”已被禁用!看看这个: //Timer is created in Class' Constructor. Class is not static. public PDAAccess () { ConnectionTimeoutChecker = new System.Timers.Timer(1000); ConnectionT

一段时间以来,我一直在经历这种反复出现的噩梦(我的应用程序中存在读取错误)。出于某种原因,某个计时器在我停止后继续发送“已用”事件,即使事件本身中的计时器“承认”已被禁用!看看这个:

//Timer is created in Class' Constructor. Class is not static.
public PDAAccess ()
{
  ConnectionTimeoutChecker = new System.Timers.Timer(1000);
  ConnectionTimeoutChecker.Elapsed += new System.Timers.ElapsedEventHandler(ConnectionTimeoutChecker_Elapsed);
}

void ConnectionTimeoutChecker_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{ //_DeviceConTimeout eventually reaches A LOT MORE than 10.
  if (_DeviceConTimeout > 10)
  {
    ConnectionTimeoutChecker.Stop(); //This is invoked but the timer DOES NOT STOP.
    if (OnDeviceSyncTimeout != null) OnDeviceSyncTimeout(this, null); //This gets fired all the time.
  }
  _DeviceConTimeout++; //This keeps increasing and increasing.
  //Worth mentioning: sender = Timer, sender.Enabled = false (!) so then why is this executing?
}
至于从哪里开始:我在一个地方开始,我在那里放了一个断点,它不会执行多次。在您提问之前:不涉及多个线程。我在这个应用程序中使用线程,但是:计时器不是在线程中创建的,类也不是

然而。停止();执行100次,计时器仍然不会停止


我在这里完全不知所措。这种行为对我来说太奇怪了,它给我一种尴尬的感觉,我可能错过了一些非常明显的东西。有时写这样一篇文章可以帮助我在点击提交按钮之前发现问题(我们都知道“向第三方解释”的效果)。但它还没击中我所以我要按下按钮。。。看看你看到了什么::-D.

在黑暗中拍摄:也许调用
OnDeviceSyncTimeout()
会间接地导致计时器被重新激活?我知道你说它只在一个地方开始,但我不确定你怎么能这么肯定。

好吧,这对你发布的代码片段没有多大意义。但像这样的特殊问题需要特殊的解释

System.Timers.Timer类是一个可怕的计时器。您看到的情况是,在计时器停止时调用经过的事件,这在大多数情况下都是不可避免的。问题在于,它使用ThreadPool.QueueUserWorkItem()引发已用事件。该线程受线程池调度程序和Windows线程调度程序的影响。QUWI不保证线程会立即运行。相反,线程以“准备运行”状态进入队列。TP调度器仅在认为运行线程的时间合适时才将其从该队列中删除。这就意味着,如果它运行的线程数量与您的机器运行的CPU内核数量相同,那么它将被卡住一段时间。只有当线程未完成时,才会允许更多线程运行。这需要一段时间,这些调度决策每秒只运行两次

Windows线程调度程序也起作用。当机器被加载时,有许多线程准备好运行,那么在经过的线程开始运行之前可能需要一段时间。这个问题特别令人讨厌的是,这样的竞赛严重依赖于程序或机器中正在发生的其他事情。在您的开发人员机器上运行良好,当经过的事件最终运行时,在生产中出现不可预测的故障,即使计时器很久以前就停止了

还请注意,这可能会累积。您尤其容易受到这种情况的影响,因为您会在经过的事件中停止计时器。当TP线程无法调度时,计时器会一直调用QUWI,添加更多TP线程,而您的代码无法停止计时器


好吧,猜猜,但它确实解释了问题。UI库中的同步计时器或System.Thread.timer都应该修复它。请尝试使用后者的单镜头版本。超时是一个固定的时间,它不应该被计算。

是否可以在一个简单的应用程序中仅使用相关的代码来重现错误?是否确定
ConnectionTimeoutChecker.Stop()
与构造函数中的
ConnectionTimeoutChecker
实例是否相同?您在那里有一个奇怪的缩进,这表明您的构造函数和
ConnectionTimeoutChecker\u可能处于不同的上下文中。@Mark:如果我得出结论,到目前为止我没有做任何愚蠢的事情,我将继续努力。我想可能在某个地方有个愚蠢的错误,我会被指出::-D.@ikrz:很抱歉这个错误的缩进。我会修好的。是的,是同一个例子。没有计时器或类的多个实例。另外:完全奇怪的是,正如我所说,在计时器本身中,“发送者”将自己标识为禁用的计时器。非常奇怪。如果是那样的话,我不得不同意Timwi的建议,你实际上正在重新激活它。。。否则,请提供您的其余代码,以便我们查看是否存在错误。正如我所说,我在启动它的位置放置了一个断点。它不会被击中。我没有在任何地方重新启动计时器。没有,没有重新激活。我将断点放在唯一执行ConnectionTimeoutChecker.Start()的位置;它没有击中它。嗨,汉斯,谢谢你的描述性信息。事实上,我在这个应用程序中经常使用ThreadPool.QueueUserWorkItem()。即使这个类也使用它,但只有在建立了连接之后。计时器对象和事件挂钩/取消挂钩与该函数无关。你是对的,一个人就足够了。我甚至不知道我为什么这样做::-D。这太愚蠢了。但这不是重点。这个类的工作原理是这样的:等待连接,然后,当连接建立时,用.Stop关闭计时器,并启动一个线程来做一些事情。您可能会感兴趣的是,哪个线程可以处理这种情况。顺便说一句,
System.Threading.Timer
与UI计时器有相同的问题(除非在对信号进行操作之前仔细检查是否禁用)。