在下面的C#代码中,从计时器线程调用System.Timers.Timer.Stop,但也从UI线程调用:
private void StartTimer()
{
// This is in the context of the UI thread.
this.m_timer = new System.Timers.Timer(1000);
this.m_timer.Elapsed += (sender, e) =>
{
// This is in the context of the timer thread.
try
{
this.m_timer.Stop();
// Do some stuff.
this.m_timer.Start();
}
catch (Exception exception)
{
CTrace.Exception(this, "StartTimer", exception);
}
};
this.m_timer.Start();
}
// After returning from the StartTimer() method, this.m_timer.Stop()
// will be called from the UI thread.
从计时器线程安全调用System.Timers.Timer.Start
和System.Timers.Timer.Stop
吗?它是线程安全的吗?
谢谢!
答案 0 :(得分:1)
不,Stop()
和Start()
方法在MSDN的文档中未列为线程安全。
为了最安全,您应该在使用多个线程时锁定MSDN中未列为线程安全的所有操作。
然而,您的代码还有其他问题,您在启动新计时器时会替换this.m_timer
,但是在计时器回调代码中您也使用this.m_timer
,这意味着如果您启动计时器然后启动第二个回调将使用相同的m_timer
。您应该只使用一个计时器而不是在启动函数内创建它。
此外,您无需手动停止将计时器设置AutoReset
设置为false
,而是提供您尝试自动执行的操作。
private object m_timerLock;
private bool m_timerRunning = false;
public YourClass()
{
this.m_timer = new System.Timers.Timer(1000);
this.m_timer.AutoReset = false;
this.m_timer.Elapsed += TimerCallback;
}
private void StartTimer()
{
// This is in the context of the UI thread.
lock(this.m_timerLock)
{
this.m_timerRunning = true;
this.m_timer.Start();
}
}
private void TimerCallback(object sender, EventArgs e)
{
// This is in the context of the timer thread.
try
{
//This line is not needed anymore because of the this.m_timer.AutoReset = false.
//this.m_timer.Stop();
// Do some stuff.
lock(this.m_timerLock)
{
//This checks to see if StopTimer() was called while the callback was running.
if(this.m_timerRunning)
this.m_timer.Start();
}
}
catch (Exception exception)
{
CTrace.Exception(this, "StartTimer", exception);
}
}
public void StopTimer()
{
lock(this.m_timerLock)
{
this.m_timer.Stop();
this.m_timerRunning = false;
}
}