另一种方法是在前一个线程仍然繁忙时让Timer跳过
本文关键字:跳过 Timer 线程 一个 方法 另一种 | 更新日期: 2023-09-27 17:52:48
我有同样的问题,如在本主题中描述的如何让定时器跳过tick如果前一个线程仍然忙
我不知道我是否应该为我的问题创建新主题,或者我可以"up"某种存在的线程(请让我知道如果我创建新主题是错误的)
我写了这样的解决方案:
Mutex refreshMutex = new Mutex();
void OnRefreshTimedEvent(object source, ElapsedEventArgs args)
{
try
{
refreshMutex.WaitOne();
// do work
} finally
{
refreshMutex.ReleaseMutex();
}
}
我认为它更好,因为它是线程安全的,不锁定整个对象。我非常感谢任何的评论,因为我对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();
}
}
这实际上并不能解决问题。在线程池线程上引发Elapsed事件。当应用程序中有很多活动的TP线程时,调用Elapsed事件处理程序的线程可能需要几秒钟才能开始运行。事实上,当这种延迟发生时,其中几个可能会被安排。停止计时器不会阻止这些延迟线程运行。您仍然可以有多个线程并发地调用您的Elapsed事件处理程序。
设置定时器的AutoReset属性为False。在Elapsed事件处理程序的finally块中调用计时器的Start()方法使其再次运行。或者使用一个周期为0的System.Threading.Timer。这是一个全面更好的计时器,它不会在没有诊断的情况下吞下异常,就像System.Timers.Timer那样。
也许我错过了一些东西,但为什么不禁用定时器上的自动复位(假设您正在使用System.Timers)。定时器-你没有指定)?在经过的处理程序impl周围放一个try/finally,以确保Start()在完成时总是被调用。这样,计时器将不会再次启动,直到Elapsed处理程序完成。