如何正确停止计时器
How to properly stop a timer
using System.Timers;
void CreateTimer()
{
myTimerObject = new Timer(5000);
myTimerObject.AutoReset = false;
myTimerObject.Elapsed += MyEventOnElapsed;
myTimerObject.Start();
}
void MyEventOnElapsed(object sender, ElapsedEventArgs e)
{
lock(aLockObject)
{
myTimerObject.Stop();
// Perform actions that can exceed the interval time set in the timer
myTimerObject.Start();
}
}
void MethodTrigerredToStopTimer()
{
lock(aLockObject)
{
myTimerObject.Stop();
}
}
在上面的代码中,我经过的事件 (MyEventOnElapsed
) 需要一段时间才能完成,因此我不得不使用计时器启动和停止作为该方法的一部分。当 MethodTriggeredToStopTimer
被触发时,我们假设代码在 MyEventOnElapsed
并达到锁定,但是 MethodTriggerredToStopTimer
的线程赢得了比赛并设法获得了锁,我的计时器将被停止MethodTriggeredToStopTimer()
。然而一旦锁被释放,在MyEventOnElapsed
中的锁(aLockObject
)处等待的执行指针将无限期地继续start/stop计时器。在这种情况下如何处理定时器?
如果您希望在管理这样的循环时通过方法调用或触发器以明确的方式停止,您将需要维护一些 boolean isStopped
或类似的:
boolean isStopped = false;
void CreateTimer()
{
myTimerObject = new Timer(5000);
myTimerObject.AutoReset = false;
myTimerObject.Elapsed += MyEventOnElapsed;
myTimerObject.Start();
}
void MyEventOnElapsed(object sender, ElapsedEventArgs e)
{
lock(aLockObject)
{
if (isStopped)
return;
myTimerObject.Stop();
// Perform actions that can exceed the interval time set in the timer
myTimerObject.Start();
}
}
void MethodTrigerredToStopTimer()
{
lock(aLockObject)
{
isStopped = true;
myTimerObject.Stop();
}
}
这一切在一个漂亮的小包装器 class 中会更加整洁,状态变量的名称类似于 Enabled
以避免与 Timer
的命名相似性混淆start
和 stop
方法。此外,如果您最终需要跨平台支持或想要在您的过程中处理诸如取消之类的事情,我也会看一下使用 Task
、Task.Delay
和 CancellationToken
构建此循环long-运行 操作.
一个选项是在停止(禁用)它之前询问计时器是否启用了 Timer
。 这样,如果调用 MethodTrigerredToStopTimer
,它将意识到它已被故意停止,而不会再次启动它。
void MyEventOnElapsed(object sender, ElapsedEventArgs e)
{
lock(aLockObject)
{
if (myTimerObject.Enabled)
{ try
{
myTimerObject.Stop();
// Perform actions that can exceed the interval time set in the timer
}
finally
{
myTimerObject.Start();
}
}
}
}
try finally
有助于确保在您退出 lock
时重新启动计时器(即使抛出异常)。
using System.Timers;
void CreateTimer()
{
myTimerObject = new Timer(5000);
myTimerObject.AutoReset = false;
myTimerObject.Elapsed += MyEventOnElapsed;
myTimerObject.Start();
}
void MyEventOnElapsed(object sender, ElapsedEventArgs e)
{
lock(aLockObject)
{
myTimerObject.Stop();
// Perform actions that can exceed the interval time set in the timer
myTimerObject.Start();
}
}
void MethodTrigerredToStopTimer()
{
lock(aLockObject)
{
myTimerObject.Stop();
}
}
在上面的代码中,我经过的事件 (MyEventOnElapsed
) 需要一段时间才能完成,因此我不得不使用计时器启动和停止作为该方法的一部分。当 MethodTriggeredToStopTimer
被触发时,我们假设代码在 MyEventOnElapsed
并达到锁定,但是 MethodTriggerredToStopTimer
的线程赢得了比赛并设法获得了锁,我的计时器将被停止MethodTriggeredToStopTimer()
。然而一旦锁被释放,在MyEventOnElapsed
中的锁(aLockObject
)处等待的执行指针将无限期地继续start/stop计时器。在这种情况下如何处理定时器?
如果您希望在管理这样的循环时通过方法调用或触发器以明确的方式停止,您将需要维护一些 boolean isStopped
或类似的:
boolean isStopped = false;
void CreateTimer()
{
myTimerObject = new Timer(5000);
myTimerObject.AutoReset = false;
myTimerObject.Elapsed += MyEventOnElapsed;
myTimerObject.Start();
}
void MyEventOnElapsed(object sender, ElapsedEventArgs e)
{
lock(aLockObject)
{
if (isStopped)
return;
myTimerObject.Stop();
// Perform actions that can exceed the interval time set in the timer
myTimerObject.Start();
}
}
void MethodTrigerredToStopTimer()
{
lock(aLockObject)
{
isStopped = true;
myTimerObject.Stop();
}
}
这一切在一个漂亮的小包装器 class 中会更加整洁,状态变量的名称类似于 Enabled
以避免与 Timer
的命名相似性混淆start
和 stop
方法。此外,如果您最终需要跨平台支持或想要在您的过程中处理诸如取消之类的事情,我也会看一下使用 Task
、Task.Delay
和 CancellationToken
构建此循环long-运行 操作.
一个选项是在停止(禁用)它之前询问计时器是否启用了 Timer
。 这样,如果调用 MethodTrigerredToStopTimer
,它将意识到它已被故意停止,而不会再次启动它。
void MyEventOnElapsed(object sender, ElapsedEventArgs e)
{
lock(aLockObject)
{
if (myTimerObject.Enabled)
{ try
{
myTimerObject.Stop();
// Perform actions that can exceed the interval time set in the timer
}
finally
{
myTimerObject.Start();
}
}
}
}
try finally
有助于确保在您退出 lock
时重新启动计时器(即使抛出异常)。