如果前一个线程仍然忙,则让计时器跳过勾选的另一种方法

时间:2011-04-25 21:35:39

标签: c#

我遇到与本主题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();
    }
}

我认为它更好,因为它是线程安全的并且不会锁定entiry对象。我很感激任何评论因为我在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(); 
    }
}

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

也许我错过了什么,但你为什么不在计时器上禁用AutoReset(假设你使用的是System.Timers.Timer-你没有指定)?对你的Elapsed处理程序impl进行try / finally,以确保在完成后始终调用Start()。这样,在Elapsed处理程序完成之前,您的计时器不会再次启动。