【问题标题】:One another way to let Timer skip tick if the previous thread is still busy如果前一个线程仍然忙,另一种让 Timer 跳过滴答声的方法
【发布时间】:2011-04-26 09:16:46
【问题描述】:

我遇到了与本主题How to let Timer skip tick if the previous thread is still busy中描述的相同的问题

我不知道是否应该为我的问题创建新主题,或者我可以以某种方式“提升”现有线程(如果我创建新主题有误,请告诉我)

我写了这样的解决方案:

Mutex refreshMutex = new Mutex();
void OnRefreshTimedEvent(object source, ElapsedEventArgs args)
{
    try
    {
        refreshMutex.WaitOne();
        // do work
    } finally
    {
        refreshMutex.ReleaseMutex();
    }
}

我认为它更好,因为它是线程安全的并且不会锁定整个对象。我将不胜感激任何 cmets,因为我在 C# 中相当新手 :)

有人发现我分享的内容有任何潜在问题吗?我不能作为其他讨论的答案。

upd 看来上面的解决方案不起作用(感谢 user24601 的注意)。但我不喜欢引用问题的答案,因为对 serviceTimer.Stop() 的调用不是线程安全的。这在理论上(并且可能实际上)在极端频繁的计时器中可能是一个问题,特别是如果系统被密集使用(100% CPU 负载等)。我现在正在考虑这样的模式:

[MethodImpl(MethodImplOptions.Synchronized)]
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    try
    {
      serviceTimer.Stop(); 
      // do some heavy processing... 
    }
    finally
    {
      serviceTimer.Start(); 
    }
}

【问题讨论】:

  • 除了锁定之外,还有什么原因导致链接问题上提供的计时器停止/启动答案不充分?
  • 据我了解,井锁定是一个非常严重的问题。理论上,另一个线程可以在第一个线程执行 serviceTimer.Stop() 时启动该方法; (不确定这在实践中是否可行)
  • 我已经编辑了您的问题,使其不再是对另一个问题的回答,而是一个受另一个问题启发的新问题。
  • 好吧,我的答案已被删除,但至少我得到了一声呐喊!
  • 嘿,模组,为什么我的答案被删除了?这很烦人。

标签: c#


【解决方案1】:

这实际上并不能解决问题。 Elapsed 事件在线程池线程上引发。当您的应用程序中有很多活动的 TP 线程时,调用 Elapsed 事件处理程序的线程可能需要几秒钟才能开始运行。事实上,在发生这种延迟时,可能会安排其中的几个。停止计时器不会阻止这些延迟的线程运行。您仍然可以有多个线程同时调用您的 Elapsed 事件处理程序。

将计时器的 AutoReset 属性设置为 False。在 Elapsed 事件处理程序的 finally 块中调用计时器的 Start() 方法以使其再次运行。或者使用周期为 0 的 System.Threading.Timer。这是一个全面的更好的计时器,它也不会像 System.Timers.Timer 那样在没有诊断的情况下吞下异常。

【讨论】:

    【解决方案2】:

    也许我遗漏了一些东西,但是您为什么不禁用计时器上的 AutoReset(假设您使用的是 System.Timers.Timer - 您没有指定)?在您的 Elapsed 处理程序 impl 周围放置一个 try/finally 以确保 Start() 在完成时始终被调用。这样,在 Elapsed 处理程序完成之前,您的计时器不会再次启动。

    【讨论】:

      猜你喜欢
      • 2011-03-26
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多