C# 避免定时器重入的4种方法

System.Timers.Timer执行方法的时候,会开一个线程去执行,如果使用锁(方法3)避免重入,可能会有多个线程等在那里执行。

按照单片机的写法要推荐方法1

但是C#提供了方便的定时器Stop方法,所以可用方法2,但是这种方法有个弊端,就是如果要停止定时器的时候,如果有线程在执行,又会把定时器打开,所以还是推荐方法1吧。

  1. 使用标志位:设置一个标志位来跟踪定时器是否已经在执行。在定时器的回调函数中,首先检查这个标志位。如果标志位表示定时器已经在执行,则立即退出,避免重入。
private bool isTimerRunning = false;  
  
private void Timer_Elapsed(object sender, ElapsedEventArgs e)  
{  
    if (isTimerRunning) return;  
    isTimerRunning = true;  
  
    try  
    {  
        // 定时器的逻辑代码  
    }  
    finally  
    {  
        isTimerRunning = false;  
    }  
}
  1. 停止定时器:在定时器的回调函数开始时停止定时器,并在函数结束时重新启动它。这样可以确保在函数执行期间不会触发另一个回调。
private void Timer_Elapsed(object sender, ElapsedEventArgs e)  
{  
    timer.Stop();  
  
    try  
    {  
        // 定时器的逻辑代码  
    }  
    finally  
    {  
        timer.Start();  
    }  
}
  1. 使用锁:使用lock语句或Mutex来同步访问定时器回调函数中的代码。这可以确保即使多个线程同时进入回调函数,也只有一个线程可以执行其中的代码。
private object timerLock = new object();  
  
private void Timer_Elapsed(object sender, ElapsedEventArgs e)  
{  
    lock (timerLock)  
    {  
        // 定时器的逻辑代码  
    }  
}
  1. AutoReset属性:System.Timers.Timer类有一个AutoReset属性,当设置为false时,定时器在触发一次Elapsed事件后不会自动重置,需要手动重启定时器。这可以防止定时器在上一个回调还未完成时再次触发
System.Timers.Timer timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += OnTimedEvent;
timer.Start();

private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
    try  
    {  
        // 定时器的逻辑代码  
    }  
    finally  
    {  
        timer.Start();  
    }  
}

你可能感兴趣的:(c#,开发语言)