文章目录
概述
本文主要参考官方文档,加上自己的经验理解,对原生AMC框架做全面阐述。后续会有篇章专门讲述AMC框架的优化,让其成为日常编程必备的有力工具。
什么是AMC库?
异步消息通信(AMC,Asynchronous Message Communication)库是LabVIEW提供的一套通用API,用来在不同的运行单元之间传递消息。它支持三种通信场景:
- 同一进程内部
- 同一设备上不同进程之间
- 通过网络连接的不同LabVIEW目标之间
可以简单理解为:无论你的代码是在同一个循环里,还是在不同的VI里,甚至在不同的计算机上,只要能用LabVIEW运行,就能通过AMC互相“发消息”。
QMH设计模式与AMC的关系
队列消息处理器(QMH,Queued Message Handler)是一种通用的VI架构,适合当作各种LabVIEW程序的基础模板。它利用AMC来发送和接收消息,可以用来实现:
- 状态机
- 用户界面(UI)
- 异步通信处理器
- 大型应用中不同功能模块之间的交互
如果你用过“队列状态机(QSM)”的架构,那么QMH对你来说不会陌生。但它不仅限于状态机任务,还能更灵活地组织各种功能,所以命名上更能反映它的实际用途。
AMC的设计目标
AMC库的核心目标是:为本地和分布式的LabVIEW应用,提供一种简单易用、可扩展的消息传递方式。
这里的“进程”指的是程序中那些会一直运行的部分(通常是While循环或Timed循环,也可能是有限循环结构),例如:
- 用户界面VI
- I/O处理模块
- 通信模块
- 数据记录模块
- 由状态机驱动的控制模块
这些模块往往需要互相交流,比如:
- 发送命令(让对方执行某个动作)
- 发送状态更新(告诉别人我现在的运行状态)
- 发送错误或故障通知
AMC的特点是处理异步消息,也就是消息的产生时间是不确定的,一般发生频率不高。
什么时候用AMC,什么时候不用?
如果你的数据是低频、不定时产生的(例如用户点击按钮、某个设备出错),AMC非常合适。
但如果你的数据是高频、定时产生的(比如传感器的连续采样数据),AMC就不是最佳选择。这时可以考虑:
- 本地通信:用原生LabVIEW队列(速度快,开销小)
- 分布式通信:用基于TCP的传输方案,例如 Simple TCP Messaging (STM) 参考库,它专门为高吞吐量设计
安装
在安装完成LabVIEW和VI Package Manager(VIPM)之后,打开VIPM软件,等待初始化完成,搜索框输入AMC,列表里即为AMC框架,选中双击进入,点击Install,按提示一步步安装过即可。下述图片所示为安装过程。



消息(Messages)
在AMC框架中,“消息”其实就是一段打包好的数据,它被放在一个 LabVIEW的簇数据结构(Cluster) 里。
这个Cluster的结构是通过 Type Definition(TypeDef) 定义的,你可以根据实际需要添加或修改字段。
AMC自带的标准消息结构包括:
- 消息名(字符串)——用来说明这条消息的类型或用途
- 消息值(字符串)——实际传递的数据内容
- 属性(字符串键值对数组)——附加的一些参数信息
- 内部参数(如接收主机名、接收进程名等)——这些主要由AMC框架内部使用,一般不建议改动,除非你非常清楚它们的作用
图4:消息的组成部分
有些开发者习惯用 Variant 来代替字符串作为消息值,或者把属性存到Variant的属性字段里,而不是用键值对数组。如果你修改了消息TypeDef,也需要相应调整库中部分函数,如XML转换函数,以匹配新的消息类型。
本地发送消息
AMC最简单的用法,是在同一个进程的不同部分之间传递消息。
例如在 QMH(队列消息处理器)设计模式 中,UI事件结构捕获到用户操作后,会把事件打包成一条消息,通过AMC发送给消息处理器进行处理。
这种用法不仅适用于QMH,也常见于生产者/消费者这种设计模式。
在这种场景下:
- 消息是通过 LabVIEW原生队列 进行缓存的
- 发送者把消息放进队列
- 接收者从队列中取消息进行处理
图5:在LabVIEW进程内发送消息示意
进程之间的消息
如果你需要在同一台设备上的不同进程之间通信,AMC依然可以做到,因为它们可以共享一个命名队列。
原理是:
- 每个接收进程都会创建一个带名字的接收队列
- 其他进程只要知道这个队列名,就能向它发送消息
- 不管有多少个发送者,接收进程只需维护这一个队列
这样,不同进程之间就能互相发送消息,而不必为每一对进程单独建立通信连接。

跨网络发送消息
如果要把消息发到**另一台设备(远程LabVIEW目标)**上的进程,就需要用网络通信协议。
AMC选择了 UDP 协议,原因是:
- UDP是无连接的(不需要建立和维持会话)
- 更适合分布式应用中临时、低频的消息传递
- 允许在任意数量的设备之间自由发送消息
在跨网络通信中,每个接收端设备上都要运行一个 AMC Dispatcher进程:
- 它会监听一个固定的UDP端口
- 收到消息后,根据消息里带的“接收进程名”,将其转发到本地的对应消息队列
- 发送方只需要知道 目标设备IP 和 接收进程名,就能把消息送过去

AMC Dispatcher还提供一些额外的功能,例如:
- 检查某个远程进程是否存在
- 获取某个设备上正在运行的所有进程列表
异步消息通信(AMC)API
AMC 提供了一组 LabVIEW VI,用来在不同进程之间(甚至跨网络)发送和接收消息。它的功能主要分为三类:
- 发送和接收消息以及管理本地消息队列
- 管理本地和远程的AMC Dispatcher
- 注册和注销本地消息队列
在 LabVIEW 的 AMC 功能面板中,你可以看到常用 VI 集合和一些子面板。子面板中包含了更细分的功能,以及一些常用设计模式的模板(比如 QMH 模式)。

消息队列管理
AMC 中的每个接收进程都需要有一个消息队列,用来接收来自本地或远程的消息。API 提供了四个核心 VI 来管理它们:

创建消息队列(Create Message Queue)
- 用唯一的队列名创建一个新队列(通常用进程名做队列名)。
- 创建时可放入一些“初始化消息”,启动后会被优先读取。QMH 模式中常用这种方式做初始化操作。
销毁消息队列(Destroy Message Queue)
销毁消息队列(Destroy Message Queue)
- 当进程结束时,必须销毁它创建的所有消息队列,释放资源。
检查消息队列状态(Check Message Queue Status)
检查消息队列状态(Check Message Queue Status)
- 可以查看队列当前的状态,包括消息数量。
清空消息队列(Flush Message Queue)
清空消息队列(Flush Message Queue)
- 移除所有等待处理的消息,而不逐条读取,适用于需要丢弃历史消息的场景。
发送与接收消息
AMC 提供了多种发送消息的方式,适用于不同的通信场景:

Send Local Message / Send Local Messages
向本地进程发送一条或多条消息。
- 如果
Process输入为空,则直接发送到指定的Message Queue引用; - 如果填写了
Process,则会发送到对应进程名的消息队列。 - 可以设置
Priority Message,让消息插到队列最前面,优先处理。
发送网络消息(Send Network Message)
Send Network Message
向远程 LabVIEW 目标发送消息。
- 使用 UDP 将消息发送到
Receiver Host(IP 地址或主机名), - 由远程的 AMC Dispatcher 转发给
Receiver Process指定的消息队列。

Send Message
一个底层通用 VI,既能发本地消息,也能发网络消息。适合需要更灵活控制的情况。

Read Next Message
从本地消息队列中取出下一条消息。
Termination List参数可以设定终止条件,比如消息名是"Exit"时,自动让循环退出。
使用这些消息发送和读取VI,你可以快速便捷地向应用中的任意进程发送灵活的消息。请记住,如果你要向远程目标发送消息,接收方必须运行 AMC Dispatcher,否则消息无法转发到目标进程。(见下节说明)。
网络通信与AMC Dispatcher
当需要通过 以太网 接收 AMC 消息时,目标 LabVIEW 系统必须运行 AMC Dispatcher。
它是一个独立运行的 VI 进程,主要做三件事:
- 打开并监听 UDP 端口
- 接收来自网络其他设备的 AMC 消息
- 根据消息里的 Receiver Process 参数,将消息分发到本地对应的消息队列
图9:AMC Dispatcher功能面板
在常见的 LabVIEW 目标(Windows XP、Vista、LabVIEW Real-Time 系统等)上,可以通过 Dispatch Start VI 和 Dispatch Stop VI 来动态启动/停止 Dispatcher。
但在 Windows CE 目标上,Dispatcher 必须静态调用,直接放在主 VI 中与应用一起运行。此时,Dispatcher 就像一个普通子 VI,必须接收到 Exit 消息才会退出。
AMC Dispatcher 功能面板 还提供了一些辅助功能,可以用来远程验证或自动化控制其他目标。这些功能的原理是:本地 Dispatcher 向远程 Dispatcher 发送请求,再等待它返回响应。因此,本地和远程的目标都必须运行 Dispatcher。
几个常用工具:
-
Ping VI
向指定的网络目标和AMC Dispatcher发送 Ping,用来确认目标上的AMC Dispatcher 是否在运行且能收消息。
-
PingAll VI
向本地子网的所有网络目标发送 Ping,促使子网内所有AMC Dispatcher响应。此功能用于建立可接收AMC消息的本地子网目标列表。
-
Verify Queue VI
用于向指定目标发送查询,验证特定命名消息队列及其关联进程的存在。用于确认某个进程是否运行且能接收消息。
-
Get All Queues VI
用于请求指定远程目标上的所有消息队列列表。
AMC消息队列注册表(Queue Registry)
Queue Registry 是一个 功能性全局变量(Functional Global Variable),用来记录当前目标系统上所有的消息队列。

- 当你用 Create Message Queue 创建队列,或用 Destroy Message Queue 销毁队列时,这个注册表都会更新。
- Dispatcher 在响应其他设备的 “Get All Queues” 查询时,也是从这里读取数据。
可以把它理解成消息队列的电话簿,任何队列的创建和销毁都会在这里登记。
队列消息处理器(QMH)设计模式
QMH(Queue Message Handler) 是 AMC 提供的一个 VI 模板,可直接从AMC功能面板拖入空白VI图表,实现了典型的生产者-消费者架构。
它非常适合以下场景:
- 应用的用户界面(UI)消息处理
- 对话框事件响应
- 命令解析器
- 基于状态机的控制逻辑
QMH 的运行逻辑是:
- 消息产生器(可以是用户操作、通信接口、内部逻辑等)把消息放入队列
- 消息处理器(一个 While 循环 + Case 结构)从队列取出消息
- 根据消息类型进入不同的 Case 执行对应的处理逻辑
图11:队列消息处理器设计模式示意
消息队列可以有多个产生器,但在实际应用中,通常只有一个(比如 UI VI)。
同时,消息处理器也能在处理某个消息时往队列里再放新消息(例如遇到错误时发送一条错误处理消息)
在QMH的正常运行中,消息通常被放置在队列末尾,按先进先出(FIFO)顺序从队列前端处理。

在某些情况下,希望队列中新消息能尽快被处理,这时可以使用AMC库中的Priority Message标志将消息放置于队列前端,下一次消息处理器从队列取消息时优先处理该消息。

基于AMC库和LabVIEW队列实现了队列消息处理器(QMH)设计模式,实现消息存储,并采用While循环与Case结构构建消息处理器。为了简化QMH在新VI和应用中的使用,AMC库提供了一套模板和示例,安装AMC库后,QMH模板可在用户库功能面板的AMC子面板中找到。
消息定义
开发队列消息处理器时,有多种方式定义队列中存储的消息,常见的包括字符串、变体(Variant)和枚举(Enumeration),各自有不同优缺点。
AMC参考库使用字符串作为消息的基本数据类型,因其允许无需预先定义允许消息集,方便在VI或应用中自由传递任意消息。这简化了添加新消息的过程,并增强了库的通用性。但字符串类型易出错(拼写错误或添加未被消息处理器处理的消息),因此需要在消息处理器中加入错误处理逻辑以检测并报告未处理的消息。
枚举类型可用来限定应用允许的消息集合,且在编程时可防止拼写错误。但使用枚举时,每个应用都需调整允许的消息集合,导致无法用同一组VI管理多个QMH应用的消息队列。
创建消息队列与添加消息
在向队列添加消息前,必须先使用Create Message Queue VI创建队列。创建时可将若干初始消息放入队列,这些消息将在消息处理器启动时被优先处理,通常用于VI的启动或初始化。
创建队列后,可用AMC的Send Local Message VI向队列添加消息。
下图示例中,创建了消息队列并添加了三个初始消息。用户界面事件处理中,当操作员点击保存状态按钮时,会将“Write Config File”消息添加到队列。图中未显示消息处理器。

还可以通过Send Local Messages VI一次性向队列添加多条消息,消息以字符串数组形式传入。

除存储在队列的消息外,有时需要随消息传递额外数据,如值或属性,用于消息处理器中定制消息处理。消息值以字符串或字符串数组形式传递给Send Local Message(s) VI。此前图示中,“Set Clock Style”消息携带了Clock Style控件的新值作为参数。
消息处理
消息处理器循环中从队列读取消息,并通过Case结构针对每个消息类型处理。基本消息处理器包括Read Next Message VI和带有各消息独立Case的结构。

从队列读取消息
Read Next Message VI包含若干重要特性,应在消息处理器中予以关注。默认操作是返回队列中的下一条消息及其关联的值字符串和键值属性数组。消息名称用作Case结构的选择器,值和属性用于具体消息处理。
超时处理
AMC Read Next Message的超时值决定VI在队列无消息时的返回时机。若超时,VI返回空消息字符串,应在对应Case中处理。QMH模板中的消息处理Case标记为"“(空字符串)或"Wait”,当Read Next Message超时时触发。该Case可用于处理VI运行时的后台任务,如前面板更新等,也可通过在队列中放置“Wait”消息调用。
QMH终止
QMH终止需确保消息处理器和所有消息产生器(如UI事件循环)正确关闭。有时消息产生器循环可能继续运行(处理VI中其他操作),但关闭后不得再向队列添加消息。
通常,QMH响应前面板上的用户操作(如退出按钮)或应用其他部分发送的消息而终止。消息产生器会向队列添加终止消息通知消息处理器关闭,同时将True传入While循环条件终止端,关闭消息产生器循环。
当消息处理器接收到终止消息时,应在对应消息Case中执行必要操作后终止消息处理循环。Read Next Message VI可识别一个或多个终止消息,返回Exit Process输出True,用于结束处理循环。默认终止消息为“Exit”,可通过传入自定义终止消息名修改。
默认消息处理器
因使用字符串作为消息名,可能出现拼写或添加错误消息,导致消息处理器无对应Case。消息处理器的Case结构默认Case应捕获这些未定义消息。通常,这些消息是编程错误,应被报告。VI或应用完整测试后,不应再触发此默认Case。

QMH模板
AMC参考库包含QMH设计模式模板,可从AMC模板功能面板拖入空白VI图表。

QMH模板面向基于UI的VI,消息处理器处理UI事件。可在左侧消息产生器循环自定义UI事件,右侧消息处理器循环添加处理Case。
该模板可通过修改消息产生器循环适配其它类型的应用和VI,必要时也可修改消息处理器。模板应作为参考设计,根据具体应用需求定制。
示例
AMC参考库中包含多个示例,展示AMC库及QMH设计模式的使用。示例随参考库一起安装,位于 <LabVIEW>\examples\AMC\ 文件夹内。

450

被折叠的 条评论
为什么被折叠?



