应用设计模式:主/从

更新 Jan 5, 2022

主/从设计模式是LabVIEW开发人员使用的另一种基础架构。当您有两个或两个以上需要同时且连续且以不同速率运行的进程时,将使用它。如果这些过程在单个循环中运行,则可能会出现严重的时序问题。当循环的一部分执行时间比预期的时间长时,就会发生这些时序问题。如果发生这种情况,循环中的其余部分将被延迟。主/从模式包括多个并行循环。每个循环可以不同的速率执行任务。在这些并行循环中,一个循环充当主循环,另一个循环充当从循环。主循环控制所有从循环,并使用消息传递体系结构与其通信。

主/从模式是在同时收集数据时响应用户界面控件时最常用的模式。假设您要编写一个应用程序,该应用程序每五秒钟测量并记录一次缓慢变化的电压。它从传输线获取波形,并每100毫秒将其显示在图形上,还提供一个用户界面,允许用户更改每次获取的参数。
主/从设计模式非常适合此应用程序。在此应用程序中,主循环将包含用户界面。电压采集和记录将在一个从属回路中进行,而传输线采集和绘图将在另一个从属回路中进行。

涉及控制的应用程序还可以受益于主/从设计模式的使用。一个示例是用户与自由动作机械臂的交互。这种类型的应用程序非常注重控制,因为如果处理不当,可能会对手臂或周围环境造成物理损坏。例如,如果用户指示手臂停止其向下运动,但是程序被手臂旋转控件占用,则机械手可能会与支撑平台碰撞。通过将主/从设计模式应用于应用程序可以避免这种情况。在这种情况下,用户界面将由主循环处理,并且机械手臂的每个可控部分都将具有自己的从属循环。使用这种方法,手臂的每个可控部分都会有自己的循环,因此也就有自己的处理时间。
这将允许通过用户界面对机器人手臂进行更灵敏的控制。

为什么要使用主/从模式?

创建多任务应用程序时,主/从设计模式非常有优势。由于具有多循环功能,它为您提供了一种更具模块化的方法来进行应用程序开发,但最重要的是,它使您可以更好地控制应用程序的时间管理。在LabVIEW中,每个并行循环都被视为单独的任务或线程。线程被定义为可以独立于其他部分执行的程序的一部分。如果您有一个不使用单独线程的应用程序,则该应用程序将被系统解释为一个线程。当您将应用程序拆分为多个线程时,它们各自均等地共享处理时间。

这使您可以更好地控制应用程序的计时方式,并向用户提供对应用程序的更多控制权。 LabVIEW的并行特性有助于实现主/从设计模式。

对于上面的数据采集示例,我们可以想象将电压测量和波形采集放到一个循环中,而仅在循环的第50次迭代中执行电压测量。但是,与单次采集和显示波形相比,完成电压测量和将数据记录到磁盘可能需要更长的时间。如果是这种情况,则波形采集的下一个迭代将被延迟,因为它无法在上一个迭代中的所有代码完成之前开始。另外,这种架构将使得难以改变采集波形的速率而不改变将电压记录到磁盘的速率。

此应用程序的标准“主/从”设计模式方法是将采集过程置于两个单独的循环(“从”循环)中,两者均由主循环驱动,该主循环轮询用户界面(UI)控件以查看参数是否已更改。为了与从属循环进行通信,主循环将写入局部变量。这将确保每个获取过程都不会影响彼此,并且确保由用户界面引起的任何延迟(例如,弹出对话框)都不会延迟任何获取过程的迭代。

建立主/从应用程序

主/从设计模式由多个并行循环组成。控制其他所有回路的是主回路,其余回路是从动回路。一个主回路始终驱动一个或多个从属回路。由于这些循环之间直接进行数据通信会中断数据流,因此必须通过写入和读取消息传递体系结构(即LabVIEW中的局部或全局变量,事件,通知程序或队列)来完成。图1显示了如何使用共享数据将不同的环路彼此连接。

图1:主/从概述

示例-同步循环

此应用程序具有以下要求:

  • 创建一个排队的消息处理程序来处理用户界面。用户界面应包含两个带LED的切换过程按钮和一个退出按钮。

  • 创建两个单独的过程,以不同的速率(间隔为100和200 ms)打开和关闭单个LED。这两个过程将使用用户界面进行控制。


我们的第一步将是确定哪个进程将成为主进程,哪个进程将成为从属进程。在此示例中,用户界面将放置在主循环中,并且两个闪烁的LED进程将是两个从属循环。用户界面将使用局部变量控制每个从属循环的操作。

现在,我们准备开始LabVIEW Master / Slave应用程序。要查看最终的主/从应用程序,请打开所附的VI(SynchLoops.vi)。

消息体系结构(共享数据)

问题:如果多个循环尝试同时将数据写入共享变量,则无法确定最终将写入哪个值。这被称为竞争条件。

解决方案:将“获取/释放信号量”对放在写入全局的任何代码段周围。这样可以确保多个循环不会尝试同时写入全局变量。 LabVIEW随附的示例中有一对演示了信号量的用法。信号量将在写入时锁定全局数据,以避免出现竞争状况。

同步化

问题:由于主/从设计模式不基于同步,所以从属循环可能在主循环之前开始执行。因此,在从属循环开始执行之前初始化主循环可能是一个问题。

解决方案:可以使用出现来解决这类同步问题。


要查找演示使用事件的示例,请参考LabVIEW附带的示例。图2给出了有关如何使用事件的示例。


图2:发生示例