内容提要
TickerQ 是 .NET 定时调度库,通过 Source Generator 在编译期注册作业,实现零反射并支持 Native AOT,自带持久化和免费 Dashboard。文章以 OpenClaw.NET 的 /loop 命令为例,展示用每分钟心跳加内存注册表实现动态调度,并注入系统消息驱动 AI Agent 定时巡检。作者认为它适合 AOT 项目和 AI Agent 场景,但尚年轻,简单任务不必引入。
延伸解读
编译期注册如何解决反射痛点
传统调度框架依赖反射扫描程序集来发现作业,导致启动慢、运行时开销大,且方法名和 cron 表达式以字符串形式存在,错误只能在运行时暴露。TickerQ 通过 Source Generator 在编译期完成作业注册,消除了反射扫描,使 cron 错误在编译期即报错,并支持 Native AOT 裁剪。对于追求快速启动和 AOT 部署的项目,这一设计是硬性优势。
动态调度的务实变通方案
TickerQ 当前版本仅支持编译期声明 cron 表达式,无法在运行时动态创建定时任务。OpenClaw.NET 的 /loop 命令通过一个每分钟触发的编译期心跳,配合内存中的 ConcurrentDictionary 注册表,实现了动态间隔的循环调度。这种方案未修改框架,也未引入额外调度依赖,以分钟级精度满足了 AI Agent 定时巡检的需求,为类似场景提供了可复用的思路。
AI Agent 定时循环的工程要点
OpenClaw.NET 的 /loop 实现展示了几个关键设计:通过消息管道注入系统消息,避免侵入 AgentRuntime;采用双层终止机制,主路径由模型调用工具显式声明完成,备用路径检测响应文本中的终止关键词,防止无限空转;整个实现零反射,依赖源生成和 FrozenSet,确保可编译进 AOT 二进制。这些做法对构建可靠的 Agent 循环有参考价值。
适用边界与当前局限
TickerQ 适合被 Hangfire 配置或收费困扰、需要 Native AOT、免费监控面板或多节点协调的项目,以及为 AI Agent 添加定时心跳的场景。但它仍较年轻,生产验证不如老牌框架,文档尚在完善,且 /loop 的动态调度依赖内存注册表,进程重启后活跃循环会丢失。简单任务使用 PeriodicTimer 即可,不必引入框架。
Q&A
TickerQ 和 Hangfire 在作业注册方式上有什么本质区别?
TickerQ 通过 Source Generator 在编译期注册作业,实现零反射;而 Hangfire 基于反射在运行时扫描程序集发现作业。
TickerQ 如何实现动态调度?
TickerQ 本身只支持编译期声明 cron 表达式,但可以通过一个每分钟 tick 一次的 TickerQ 定时器作为心跳,配合运行时维护的 ConcurrentDictionary 内存注册表,扫描到期任务来实现动态调度。
TickerQ 支持 Native AOT 吗?
支持。TickerQ 通过 Source Generator 在编译期生成所有作业注册代码,运行时零反射,因此可裁剪、可 AOT,官方明确标注 Native AOT ready。
TickerQ 的 Dashboard 收费吗?
不收费。TickerQ 自带基于 SignalR 的实时监控面板,可以查看执行状态、失败记录、重试情况,还能直接在面板上启用或禁用 cron 作业,无需改代码或重新发布。
OpenClaw.NET 为什么选择 TickerQ 作为定时调度库?
因为 OpenClaw.NET 以 Native AOT 优先,需要零反射、可裁剪的调度库。TickerQ 的源生成和零反射特性使其能编进 AOT 二进制,cron 编译期校验,核心包零外部依赖,符合其技术选型要求。
TickerQ 目前有哪些不足?
TickerQ 还比较年轻,生产验证不如 Hangfire;文档还在追赶代码;动态调度依赖内存注册表,进程重启后活跃任务会丢失;简单场景引入框架可能过度。