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

Windows Service中如何按固定间隔(含任务耗时)执行异步任务

解决方案

1. 实现固定间隔执行(包含任务耗时)

要让任务从启动到下一次启动的间隔固定为n秒(包含任务自身耗时),核心是计算任务执行后需要补充的延迟时间,而非固定延迟5秒。

修改后的循环代码如下:

var interval = TimeSpan.FromSeconds(5); // 定义固定间隔为5秒
CancellationToken stoppingToken = new();

while (!stoppingToken.IsCancellationRequested)
{
    var loopStartTime = DateTime.UtcNow; // 记录循环起始时间(用UTC时间规避时区/夏令时问题)

    // 串行执行异步任务,确保同一时间只有一个任务在运行
    await DoJob();

    // 计算任务耗时,得出需要补充的延迟时长
    var elapsedTime = DateTime.UtcNow - loopStartTime;
    var delayTime = interval - elapsedTime;

    // 若任务耗时未超过间隔,补充剩余时间的延迟;若耗时已超,直接进入下一轮
    if (delayTime > TimeSpan.Zero)
    {
        await Task.Delay(delayTime, stoppingToken);
    }
}

同时,将DoJob中的阻塞式Thread.Sleep替换为异步非阻塞的Task.Delay,避免浪费线程资源:

private async Task DoJob()
{
    await Task.Delay(3000); // 替代Thread.Sleep(3000),符合异步编程规范
}

修改后日志会呈现固定5秒间隔的效果:

Loop started at 07.06.2024 12:01:46
Start Job at    07.06.2024 12:01:46
Ended Job at    07.06.2024 12:01:49 
Loop started at 07.06.2024 12:01:51  // 延迟2秒后启动下一轮,间隔正好5秒
Start Job at    07.06.2024 12:01:51
Ended Job at    07.06.2024 12:01:54 
Loop started at 07.06.2024 12:01:56 
Start Job at    07.06.2024 12:01:56
Ended Job at    07.06.2024 12:01:59 

2. 避免任务耗时超间隔时重复启动

上述代码通过串行执行任务(await DoJob())天然避免了重复启动:只有当前任务完全执行完毕后,才会进入下一轮循环,永远不会同时运行多个DoJob实例。

如果任务耗时超过5秒(比如DoJob耗时6秒),代码会在任务结束后直接进入下一轮循环,不会额外延迟,确保不会出现任务重叠的情况。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:14:52