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

如何在C# Windows Service中创建等待主方法结束的定时器

解决C# Windows Service定时器重叠执行问题

针对你遇到的定时器在前一次ImportXML方法执行完成前就触发的问题,这里提供几种实用的解决方案:

方案一:执行前停止定时器,完成后重启

这是最直接的处理方式,在方法开始时停止定时器,确保当前执行过程中不会触发新的调用,执行完成(包括异常情况)后再重启定时器:

private void ImportXML(object sender, ElapsedEventArgs e)
{
    var timer = sender as System.Timers.Timer;
    timer.Stop();
    try
    {
        // 这里放置你的XML导入业务逻辑
        // ...
    }
    finally
    {
        // 无论执行成功还是失败,都重启定时器
        timer.Start();
    }
}

这种方式能保证每次任务执行完成后,才会开始下一个周期的计时。

方案二:使用锁跳过重叠触发

如果希望当前任务在执行时,忽略后续的定时器触发(而不是等待),可以用排他锁来控制:

private static readonly object _executeLock = new object();

private void ImportXML(object sender, ElapsedEventArgs e)
{
    // 尝试获取锁,获取失败说明已有任务在执行,直接返回
    if (!Monitor.TryEnter(_executeLock))
    {
        return;
    }
    try
    {
        // 你的XML导入业务逻辑
        // ...
    }
    finally
    {
        Monitor.Exit(_executeLock);
    }
}

这种方式下,若前一次任务还未完成,新的定时器触发会直接跳过,不会堆积任务。

方案三:改用System.Threading.Timer控制执行间隔

如果需要严格保证两次任务执行结束之间的间隔为1小时,可以使用System.Threading.Timer,它支持在任务完成后再安排下一次执行:

private System.Threading.Timer _taskTimer;
private const int OneHourMs = 3600000; // 1小时对应的毫秒数

// 在服务启动方法中初始化定时器
public void OnStart(string[] args)
{
    // 首次立即执行,后续执行完成后间隔1小时再触发
    _taskTimer = new System.Threading.Timer(ExecuteImport, null, 0, Timeout.Infinite);
}

private void ExecuteImport(object state)
{
    try
    {
        // 调用你的XML导入方法
        ImportXML();
    }
    finally
    {
        // 安排下一次执行,间隔1小时
        _taskTimer.Change(OneHourMs, Timeout.Infinite);
    }
}

// 原有的XML导入方法
private void ImportXML()
{
    // ... 业务逻辑 ...
}

这种方式的计时是从任务结束时开始算,避免了固定时间点触发导致的重叠问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:55:04