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

C#中实现每60秒执行函数且避免重复执行长耗时任务

C# Timer 实现跳过正在执行的任务周期

核心思路很直接:用一个线程安全的标记跟踪任务运行状态,每次Timer触发时先检查标记——任务没在执行就启动,正在执行就直接跳过当前周期,等下一个60秒再重新检查。

具体实现步骤

1. 定义线程安全的执行标记

Timer的Tick事件由线程池线程触发,和任务执行线程可能不是同一个,必须用原子操作保证标记的可靠性,这里用Interlocked类来操作标记:

// 0 = 任务未执行,1 = 任务正在执行
private int _isTaskRunning = 0;
private Timer _timer;

2. 初始化Timer并修改Tick事件逻辑

在Tick事件中,先尝试将标记设为“正在执行”,如果设置成功(说明之前无任务运行),就执行长耗时任务;如果失败,直接跳过本次触发:

public void SetupTimer()
{
    _timer = new Timer();
    _timer.Tick += OnTimerTick;
    _timer.Interval = 60 * 1000; // 60秒触发间隔
    _timer.Start();
}

private void OnTimerTick(object sender, EventArgs e)
{
    // 原子操作:尝试把_isTaskRunning从0改为1,返回修改前的值
    if (Interlocked.Exchange(ref _isTaskRunning, 1) == 0)
    {
        try
        {
            // 执行你的长耗时任务
            RunLongRunningProcess();
        }
        finally
        {
            // 无论任务成功/失败,都重置标记,确保后续任务能正常触发
            Interlocked.Exchange(ref _isTaskRunning, 0);
        }
    }
    // 如果Exchange返回非0,说明任务仍在运行,直接跳过本次触发
}

private void RunLongRunningProcess()
{
    // 这里写你的长运行进程逻辑,比如耗时数分钟的操作
    // 示例:模拟5秒耗时任务
    Thread.Sleep(5000);
}

关键细节说明

  • Interlocked.Exchange是原子操作,彻底避免多线程下的竞态问题,保证标记状态绝对准确。
  • try/finally块是核心:哪怕任务抛出异常,标记也会被重置,不会出现“任务永远被标记为正在执行”的死锁情况。
  • 这种逻辑完全匹配你的需求:每次Timer到点就检查任务状态,正在执行就跳过,否则执行,循环往复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:55:24