如何注册子VI(LabVIEW)中定义的用户事件

如何注册子VI(LabVIEW)中定义的用户事件,labview,Labview,我创建了一个子VI,并在其中定义了一个用户事件。 然后我创建了另一个VI,我们称之为主VI。 我在主VI中放置了一个子VI,我想将子VI中创建的用户事件注册到主VI中的事件案例中,我应该怎么做?您可以这样做,但这需要付出努力。您试图做的通常是一个坏主意——正如您在下面的步骤中看到的,您必须与LabVIEW进行多大的斗争。但是因为有时候(很少)需要,我会告诉你怎么做。但是,一般来说,当您不得不这么做时,您可能需要重新考虑,让调用方VI分配事件refnum,然后将其传递给子VI,并且只让子VI生成事

我创建了一个子VI,并在其中定义了一个用户事件。 然后我创建了另一个VI,我们称之为主VI。
我在主VI中放置了一个子VI,我想将子VI中创建的用户事件注册到主VI中的事件案例中,我应该怎么做?

您可以这样做,但这需要付出努力。您试图做的通常是一个坏主意——正如您在下面的步骤中看到的,您必须与LabVIEW进行多大的斗争。但是因为有时候(很少)需要,我会告诉你怎么做。但是,一般来说,当您不得不这么做时,您可能需要重新考虑,让调用方VI分配事件refnum,然后将其传递给子VI,并且只让子VI生成事件

无论如何。。。这是你想要的

选择1 步骤一:在调用者VI中,使用“获取队列”并创建用户事件类型的队列(这意味着您需要删除连接到“获取队列”元素类型终端的所需事件refnum类型的常量)

第二步:将队列添加到subVI的连接器窗格,并将创建的队列连接到subVI上的新终端

第三步:修改子vi,以便在创建用户事件后,使用“Enqueue元素”将该用户事件排入队列

第四步:回到调用者VI中,在与子VI调用并行的中,执行“出列元素”。现在调用者中有了用户事件

第五步:在调用者VI中使用Release Queue来释放队列

第六步:在调用者VI中,使用“注册事件”来注册用户事件。现在,您可以在事件结构中接收事件了

注意:上述过程不能保证调用方VI会在子VI开始发送事件之前注册事件。如果subVI在调用Register For events节点之前开始发送事件,您将错过这些初始事件。您需要第二个信号机制来告诉subVI“好的,可以安全地继续”

选择2 第一步:在子vi中的所有代码周围放置一个巨大的case结构。接线?带有布尔控件的case结构的终端。将该布尔控件添加到子vi的连接器窗格中。现在,subVI的所有代码都是结构的真实情况

第二步:如果为FALSE,则输入代码以创建用户事件。创建用户事件的指示器并将其放在连接器窗格上

第三步:使用案例结构之外的反馈节点来存储用户事件。不要提供任何反馈节点的初始化

第三步:在调用者中,使用连接到其输入的FALSE调用subVI。子vi将分配事件refnum并将其返回给您。它还将在反馈节点中存储refnum

第四步:使用Register For Events节点在调用者VI中注册事件

第五步:再次调用subVI,这次通过TRUE。它将从反馈节点获取用户事件refnum的值


注意:此版本确实提供了防止丢失第一个事件的保护。

选项2不需要布尔控制(至少对于LabVIEW 2018+)-子VI可以使用第一个调用函数,当它返回True时,设置调用方所需的一切(可能事件refnum不是唯一需要的东西-可能是一个类型为空的集群,稍后将用于传递数据)并返回-调用者获取并处理所有数据,然后再次调用subVI;然后第一次调用返回False,subVI“永远”保持活动状态

另一种方法是使用两个subVI-s:subVI_init和subVI_stay-调用者需要调用两个,从第一个到第二个的有线连接,但“error out”行除外,它必须通过事件寄存器,以确保在调用subVI_stay之前完成


或者-如果在子VI中创建用户事件的主要原因是事件使用的复杂数据结构,如大型且可能嵌套的集群(问题是在调用者中创建事件需要访问空结构,而将其放入调用者可能会使调用者太大)-使用单独的subVI_typedef。

选择了选项1,谢谢!选项1很难看,但选项2很糟糕。我想今晚我会为此做噩梦。读者们,请不要这样做。+1回答这个问题!@nekomatic我已经要求程序员尽量避免整个设置,但如果他们要这样做,他们真的需要一个避免竞争条件的解决方案。如果你有第三种选择可以避免竞争,请发布。但如果丑陋是唯一有效的解决方案,我主张使用工作版本,而不是漂亮但有缺陷的解决方案。我有点开玩笑:我想不出一个解决方案不涉及轮询或使用两个通信c通道。我可能会在稍后发布。但未初始化的反馈节点或移位寄存器也有自己的问题,特别是在开发过程中。实际上,更仔细地阅读选项2,它并不像我想的那么可怕。如果用状态为(例如)的typedef枚举替换布尔大小写选择器
Initialise Event
Run
则几乎没有问题。不用说subVI必须有错误输入/输出,您可以使用它来确保Initialise调用在Run subVI调用之前运行的事件的寄存器之前运行。但是如果这样做的话……为什么不在调用程序中创建事件并将其传递给subVI呢VI?:-?正如srm所指出的,在调用方VI中创建事件并将其refnum传递给子VI要好得多(这意味着对查看代码的其他人来说更容易理解,也不那么令人惊讶)。您有什么理由不能这样做吗?