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

使用CancellationTokenSource设置20秒超时,回调计算时间小于设定值的问题

为什么CancellationTokenSource.CancelAfter(20秒)会在不到20秒时触发取消?

我在使用CancellationTokenSource设置20秒超时,通过cts.Token.Register委托计算从启动到取消的时间时,偶尔会得到小于20秒的结果(比如19.999474)。这个问题是随机出现的,Windows系统上复现不了,但在Ubuntu环境里很容易触发。

测试代码

for (int i = 0; i < 50; i++)
{
    var cts = new CancellationTokenSource();

    var startTime = DateTime.Now;
    cts.Token.Register(() =>
    {
        Console.WriteLine((DateTime.Now - startTime).TotalSeconds);
    });
    cts.CancelAfter(TimeSpan.FromSeconds(20));

    Task.Run(async () =>
    {
        while (!cts.IsCancellationRequested)
        {
            await Task.Delay(1000, cts.Token);
        }
    }, cts.Token);
}

Console.WriteLine("Hello, World!");
Console.Read();

Ubuntu下的输出示例

/console# dotnet ConsoleApp.dll
Hello, World!
20.021207
19.999749
19.9997085
19.9997404
19.999752
...(其余输出省略)

环境信息

/console# dotnet --info

global.json file:
  Not found

Host:
  Version:      6.0.15
  Architecture: x64
  Commit:       5edef4b20b

.NET SDKs installed:
  No SDKs were found.

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.15 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.15 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

问题原因

  1. 系统定时器精度差异:Windows和Linux上的定时器实现机制不同,Linux下的定时器精度和调度策略可能导致取消信号提前几毫秒触发。操作系统的定时器本身就不是绝对精确的,多任务环境下的进程调度延迟会影响触发时机。
  2. DateTime.Now的精度限制:DateTime.Now依赖系统时钟,其精度在不同系统上有差异,用来测量短时间间隔时容易出现误差。

解决办法

  1. 改用Stopwatch测量时间:Stopwatch基于系统高分辨率计时器,精度远高于DateTime.Now,能更准确地记录时间间隔。修改后的代码如下:
for (int i = 0; i < 50; i++)
{
    var cts = new CancellationTokenSource();

    var stopwatch = Stopwatch.StartNew();
    cts.Token.Register(() =>
    {
        stopwatch.Stop();
        Console.WriteLine(stopwatch.Elapsed.TotalSeconds);
    });
    cts.CancelAfter(TimeSpan.FromSeconds(20));

    Task.Run(async () =>
    {
        while (!cts.IsCancellationRequested)
        {
            await Task.Delay(1000, cts.Token);
        }
    }, cts.Token);
}

Console.WriteLine("Hello, World!");
Console.Read();
  1. 接受微小误差:操作系统层面无法做到绝对精确的定时,几毫秒的偏差属于正常范围。如果业务逻辑对这几毫秒的误差敏感,可适当调整超时时间(比如设置为20.001秒),但一般情况下无需特殊处理。

内容的提问来源于stack exchange,提问作者Mr. Mantou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 16:20:32