You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保证System.Timers.Timer触发的Elapsed事件处理程序按顺序执行

解决方案

System.Timers.Timer 默认会在线程池线程上触发 Elapsed 事件,如果前一次事件处理未完成,到达间隔时间后会再次拉起新的线程执行处理逻辑,因此会出现并发执行、顺序混乱的问题,以下是两种常用的实现顺序执行的方案:


方案1:通过 AutoReset 属性控制单次触发

实现思路

将 Timer 的 AutoReset 属性设为 false,让 Timer 仅触发一次 Elapsed 事件,待本次事件处理逻辑完全执行完成后,再手动重启 Timer,从根源上避免并发触发。

示例代码

// 声明静态Timer方便事件处理中访问
private static System.Timers.Timer _timer;
static void Main(string[] args)
{
    _timer = new System.Timers.Timer(1000);
    // 设为false表示仅触发一次Elapsed事件
    _timer.AutoReset = false;
    _timer.Elapsed += (sender, e) => 
    {
        try
        {
            PrintToConsole();
        }
        finally
        {
            // 处理完成后重启Timer,保证下一次触发在上次处理结束后才开始计时
            _timer.Start();
        }
    };
    _timer.Start();
    Console.ReadLine();
}

private static void PrintToConsole()
{
    var randomInt = new Random().Next(1000);
    Console.WriteLine(randomInt);
    Thread.Sleep(2000);
    Console.WriteLine(randomInt);         
}

特点

两次事件触发的间隔为「事件处理耗时 + 设定的1秒间隔」,不会出现事件堆积的问题,适合对两次触发的间隔精度要求不高、不允许事件并发的场景。


方案2:通过锁实现排队执行

实现思路

通过锁对象同步事件处理逻辑,即使 Elapsed 事件多次并发触发,也必须等待前一次处理逻辑释放锁后才能执行,保证执行顺序和触发顺序一致。

示例代码

// 全局锁对象
private static readonly object _syncLock = new object();
static void Main(string[] args)
{
    var timer = new System.Timers.Timer(1000);
    timer.Elapsed += (sender, e) => PrintToConsole();
    timer.Start();
    Console.ReadLine();
}

private static void PrintToConsole()
{
    // 进入逻辑前先获取锁,未获取到则阻塞等待前一次处理完成
    lock (_syncLock)
    {
        var randomInt = new Random().Next(1000);
        Console.WriteLine(randomInt);
        Thread.Sleep(2000);
        Console.WriteLine(randomInt);         
    }
}

特点

Timer 仍然按照固定1秒间隔触发事件,但是事件处理逻辑会排队执行,如果事件处理耗时长期大于触发间隔,会导致线程池线程堆积,适合处理耗时稳定、不会长期超过触发间隔的场景。


内容的提问来源于stack exchange,提问作者Jimmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:06:03