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

C#开发API项目时如何实现每隔1-2秒定时执行指定函数

C#控制台场景下定时执行检索函数实现方案

核心逻辑说明

你当前是控制台程序架构,用switch分支处理用户输入,要实现输入2后每隔1-2秒自动执行已经调试通过的事件检索函数,核心要避开「主线程跑定时循环卡住输入监听」的坑,用后台异步任务执行定时逻辑,主线程持续响应用户输入即可。

分步实现

1. 定义全局控制变量

在Program类中添加两个静态变量,用于控制任务启停、生成随机间隔:

// 用于发送任务停止信号,比普通bool标记更安全可靠
private static CancellationTokenSource _retrieveTaskCts = null;
// 生成1-2秒随机间隔用,注意不要放到循环内实例化,否则会出现随机数重复问题
private static readonly Random _random = new Random();

2. 改造主函数的switch分支

保留你原有的登录、单次检索逻辑,新增定时任务启停控制,参考代码如下:

// 主程序输入监听循环
while (true)
{
    Console.Write("请输入操作指令:1-登录 2-启动定时事件检索 3-停止检索 其他-退出:");
    var input = Console.ReadLine()?.Trim();
    switch (input)
    {
        case "1":
            // 原有登录逻辑不需要改动,直接调用即可
            Login();
            break;
        case "2":
            // 避免重复启动任务
            if (_retrieveTaskCts != null && !_retrieveTaskCts.IsCancellationRequested)
            {
                Console.WriteLine("定时检索任务已在运行中,无需重复启动");
                break;
            }
            _retrieveTaskCts = new CancellationTokenSource();
            // 启动后台异步任务,不会阻塞主线程的输入监听
            _ = RunScheduledRetrieve(_retrieveTaskCts.Token);
            Console.WriteLine("定时检索任务已启动,执行间隔1-2秒");
            break;
        case "3":
            // 主动停止任务
            _retrieveTaskCts?.Cancel();
            _retrieveTaskCts?.Dispose();
            _retrieveTaskCts = null;
            Console.WriteLine("定时检索任务已停止");
            break;
        default:
            // 程序退出前释放资源,避免任务残留
            _retrieveTaskCts?.Cancel();
            _retrieveTaskCts?.Dispose();
            return;
    }
}

3. 实现定时执行核心方法

这个方法负责循环调用你已经写好的事件检索函数,每次执行完等待1-2秒,同时监听停止信号:

private static async Task RunScheduledRetrieve(CancellationToken stopToken)
{
    try
    {
        // 未收到停止信号就持续循环
        while (!stopToken.IsCancellationRequested)
        {
            try
            {
                // 直接替换成你已经调试通过的事件检索函数即可,不需要修改原有函数代码
                QuerySpecifiedEventInTimeRange();
                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 本次事件检索执行完成");
            }
            catch (Exception ex)
            {
                // 捕获单次执行的异常,避免一次报错导致整个定时任务终止
                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 检索执行异常:{ex.Message}");
            }
            // 生成1000-2000毫秒的随机等待时长(即1-2秒)
            int waitMilliseconds = _random.Next(1000, 2001);
            // 等待过程中监听停止信号,触发停止时可以立刻响应,不用等满等待时长
            await Task.Delay(waitMilliseconds, stopToken);
        }
    }
    catch (OperationCanceledException)
    {
        // 主动停止触发的异常属于正常流程,不需要额外处理
        Console.WriteLine("定时检索任务已正常退出");
    }
}

新手易踩的坑

  • 不要在主线程用while(true)+Thread.Sleep()写定时逻辑:会直接阻塞主线程,导致你输入其他指令完全没响应。
  • 不要每次循环都new一个Random实例:Random的种子生成依赖系统时钟,短时间内多次实例化会生成完全相同的随机数,达不到1-2秒随机间隔的效果。
  • 必须加异常捕获:接口请求超时、返回数据格式错误都可能导致检索函数抛异常,如果不捕获,整个定时任务会直接终止,不会继续执行下一次。
  • 不需要引入第三方定时任务库:这种简单的定时场景用C#原生的async/Task就能实现,新手没必要额外学Quartz、Hangfire这类重框架。
  • 如果需要固定间隔,直接把waitMilliseconds赋值为1000(1秒)或2000(2秒)即可,不需要调用Next生成随机数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:48:19