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
相关产品推荐
相关产品推荐

