我有一个 Elapsed 方法,其中有一个 while 循环。如果定时器被另一个线程禁用/停止,我希望这个循环停止。为此,我可以依赖 Elapsed 方法中计时器的 Enabled 属性吗,还是应该创建一个“volatile bool timerEnabled”变量来确定。我的测试表明它没问题,但我想在将其投入生产之前确定这一点。
这就是我想要实现的(不是实际代码,而是接近)
private volatile bool isElapsedAlreadyRunning
void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!isElapsedAlreadyRunning) // to prevent reentrance
{
isElapsedAlreadyRunning = true;
try
{
while (myTimer.Enabled && some other condition)
{
do stuff
}
}
finally
{
isElapsedAlreadyRunning = false;
}
}
}
myTimer.Start() and myTimer.Stop() are in other methods that can be called frrom other threads
我正在使用 System.Timers.Timer 类
如果您有任何其他意见或看到此设计中的任何缺陷,请随时发表评论:)
谢谢
编辑:
伙计,线程很难。基于答案和其他 stackoverflow 问题 ( this answer particularly ) 这将是这样做的方式(我希望这次没问题)
public class NoLockTimer : IDisposable
{
private readonly System.Timers.Timer _timer;
private bool _isTimerStopped = false;
private readonly object _isTimerStoppedLock = new object();
public NoLockTimer()
{
_timer = new System.Timers.Timer { AutoReset = false, Interval = 1000 };
_timer.Elapsed += delegate
{
try
{
while (!IsTimerStopped && some other condition)
{
// do stuff
}
}
catch (Exception e)
{
// Do some logging
}
finally
{
if (!IsTimerStopped)
{
_timer.Start(); // <- Manual restart.
}
}
};
_timer.Start();
}
public void Stop()
{
IsTimerStopped = true;
if (_timer != null)
{
_timer.Stop();
}
}
private bool IsTimerStopped
{
get
{
lock (_isTimerStoppedLock)
{
return _isTimerStopped;
}
}
set
{
lock (_isTimerStoppedLock)
{
_isTimerStopped = value;
}
}
}
public void Dispose()
{
Stop();
if (_timer != null)
{
_timer.Dispose();
}
}
}
最佳答案
不,这不安全。 Elapsed 事件处理程序在线程池线程上调用。您无法预测该线程何时实际调用您的方法,这取决于进程中正在运行的其他 TP 线程。同时进行两个通话在技术上是可行的。这使得 isElapsedAlreadyRunning 变量上的 volatile 关键字不足以确保该方法是线程安全的,您必须改用 lock 关键字或 Monitor.TryEnter() .
当您将 Timer 的 AutoReset 属性设置为 false 时,这个问题就会消失。确保在 finally block 中重新启动计时器,Timer.Elapsed 事件的另一个令人讨厌的问题是异常在没有诊断的情况下被吞没。 System.Threading.Timer 是一个全面的更好的计时器,这样的意外更少。
Timer.Enabled 属性也有类似的问题,你总会迟到。
关于c# - System.Timers.Timer.Enabled 属性线程安全吗,是否可以从计时器的 Elapsed 事件访问它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14564173/