消息队列处理器(QMH)是最常用的 LabVIEW 架构之一。但什么时候该用 JKI State Machine?DQMH 解决了什么问题?从设计模式的发展脉络讲起,帮你找到最适合项目需求的架构方案。

一、LabVIEW 架构设计的演进之路
一个 LabVIEW 程序员的成长,往往伴随着程序架构的不断进化。开发经历,大致经历了以下几个阶段:
|--------|--------------------------|-------------|-----------|
| 阶段 | 架构 | 典型规模 | 维护成本 |
| 入门 | 单循环 + 顺序结构 + 简单状态机 | < 50 VI | 极高(修改困难) |
| 初级 | 多循环(生产者-消费者) | 50~200 VI | 高(协调复杂) |
| 中级 | QMH(队列消息处理器) | 200~500 VI | 中(模块化好) |
| 高级 | JKI State Machine / DQMH | 500+ VI | 低(标准化框架) |
| 专家 | Actor Framework / 自定义框架 | 1000+ VI | 极低(高度组件化) |
每个阶段的跃升,都意味着对 LabVIEW 编程模型的理解更加深入。
二、QMH(Queued Message Handler)深入分析
2.1 什么是 QMH?
QMH 是 NI 官方推荐的标准架构之一。它的核心思想是:
- 一个事件循环(Event Handling Loop)负责接收用户操作和外部事件
- 事件循环将操作转换为消息(字符串或 Enum),放入队列
- 一个消息循环(Message Handling Loop)从队列取出消息并执行对应操作
2.2 QMH 的优势
- 结构清晰:事件处理与业务逻辑分离
- 扩展性好:新增功能只需增加新的消息类型和处理分支
- 线程安全:队列保证了消息的有序传递
- NI 原生支持:LabVIEW 内置 QMH 项目模板
2.3 QMH 的局限
在实际项目中,我们发现 QMH 存在一些天然的局限:
- 两个循环需要重复定义消息类型和数据
- 跨循环的数据共享需要额外的 FGV 或 User Event
- 复杂状态流转的逻辑不够直观
- 当项目规模超过 500 VI 时,消息管理变得混乱
三、JKI State Machine:轻量级架构的优雅解决方案
3.1 JKI State Machine 的核心思想
JKI State Machine(以下简称 JKI SM)由 Jim Kring 设计,是一个开源的 LabVIEW 架构模板。它在 QMH 的基础上做了三件事:
- 将「状态字符串」始终暴露在顶层 VI 中,程序流程一目了然
- 使用队列作为核心数据通道,但设计上更简洁
- 提供 IDE 集成工具(Quick Drop 快捷键、右键菜单),提升开发效率
3.2 五大最佳实践
JKI 团队总结的 5 个最佳实践,值得每个 LabVIEW 开发者牢记:
最佳实践 1:不要把状态字符串藏在子 VI 中
状态字符串应该在顶层 VI 中可见。这样当你在分析和调试时,一眼就能看明白程序的执行流程。如果状态字符串被埋藏在子 VI 里,阅读代码的人需要层层深入才能搞清楚程序在做什么。
最佳实践 2:不要在 Event Structure 中写业务逻辑
Event Structure 的职责只应该是「接收事件并分发」。真正的业务逻辑应该放在对应的状态分支中。这保持了两者各司其职,Event Structure 保持简洁,状态分支专注业务。
最佳实践 3:保持结构原有尺寸
不要随意增大 Case Structure 和 Event Structure 的原始尺寸。这看起来是个细节,但它强制你保持关注点分离------如果觉得状态太多,说明应该拆分子 VI 了。
最佳实践 4:使用宏替代顺序状态链
如果有一串固定的状态需要顺序执行(比如初始化 → 自检 → 等待 → 运行),不要硬编码一串连续的「跳转」。使用宏(Macro)将一组状态聚合成一个逻辑单元。
最佳实践 5:状态字符串左对齐
左对齐的状态字符串比右对齐更容易阅读和排序。JKI SM 默认采用左对齐。
四、DQMH:大型团队的协作框架
4.1 DQMH 做了什么优化?
Delacor Queued Message Handler(DQMH)在 QMH 的基础上引入模块化设计:
- 模块封装:每个 DQMH 模块是一个独立的 QMH,拥有自己的事件循环和消息循环
- 接口标准化:模块之间通过「广播消息」和「请求-响应」两种模式通信
- 代码生成:DQMH 提供了模块模板生成工具,一键创建新模块
- 测试友好:每个模块可以独立测试
4.2 DQMH vs JKI SM 选型建议
|----------|-----------------------|--------------|
| 对比维度 | JKI State Machine | DQMH |
| 团队规模 | 1~3 人 | 3 人以上 |
| 项目规模 | < 300 VI | 300~2000 VI |
| 学习曲线 | 低(1~2 天) | 中(1~2 周) |
| 模块化程度 | 低(整体架构) | 高(模块化) |
| 代码生成 | 部分支持 | 完整支持 |
| NI 生态 | 开源,广泛使用 | 开源,NI 推荐 |
五、参考架构:事件队列+操作队列双通道设计
5.1 架构设计
我们在多个自动化测试项目中采用的双通道架构:
【UI 事件循环】Event Structure 监听用户操作 ↓ 操作消息队列(Queue) 【调度循环】解析消息 → 调用对应处理模块 ↓ 数据队列 / User Event 【执行模块】测试执行 / 数据记录 / 报表生成
5.2 为什么这样设计?
- UI 事件循环只在前面板有交互时才唤醒,不占 CPU
- 调度循环集中管理所有状态流转,逻辑清晰
- 执行模块独立运行,某个模块出错不影响其他模块
- 队列提供背压缓冲,防止操作洪峰导致数据丢失
六、工程实战经验
6.1 关于「QMH 是否已过时」的讨论
这是一个在 NI 社区中热议的话题。我们的观点是:QMH 没有过时,它是理解更高级架构的必经之路。就像学编程语言要先学变量和循环才能学面向对象一样,先掌握 QMH 才能理解 DQMH 和 Actor Framework 为什么这样设计。
6.2 从我们的项目看架构选型
|----------|-----------------|---------------|
| 项目类型 | 推荐架构 | 原因 |
| 单机数据采集 | QMH 或 JKI SM | 简单够用,学习成本低 |
| 自动化测试平台 | DQMH 模块化 | 多测试项独立开发,团队协作 |
| 长期监控系统 | QMH + 生产者-消费者 | 稳定可靠,7×24 运行 |
| 复杂仪器控制 | JKI SM | 状态流转清晰,调试方便 |
| 大型分布式系统 | Actor Framework | 消息传递模式天然适合分布式 |
七、总结
选择 LabVIEW 架构没有「银弹」。QMH 适合中小项目快速开发,JKI State Machine 在状态管理上有独特优势,DQMH 为大型团队协作而生,Actor Framework 则是企业级分布式系统的终极方案。
我们在项目中的原则是:能用简单的绝不用复杂的。先从 QMH 开始,当项目复杂度确实超出 QMH 的能力范围时,再平滑迁移到 JKI SM 或 DQMH。