LabVIEW事件结构的妙用
- 格式:pdf
- 大小:326.04 KB
- 文档页数:8
reference死锁问题LabVIEW中的引用经常需要和“In Place Element Structure”配合使用。
In Place Element Structure 对一个引用的数据进行处理时,为了保证多线程安全,它会锁住引用指向的数据;其它线程若需对同一数据做操作,必须能这个In Place Element Structure中所有代码执行完毕才可,这样就避免了多线程读写同一内存数据所产生的竞争问题。
举例来说,下面这段程序的执行时间是1秒:而下面这段程序的执行时间则是2秒:因为第二段程序中的两个In Place Element Structure必须顺序执行。
有了“锁住”这个操作,就有不小心造成死锁的可能。
比如对于同一数据的引用,千万不能嵌套使用In Place Element Structure,否则就会死锁:在上面这个示例中,程序运行至内层的In Place Element Structure,就会停在这里等外层In Place Element Structure运行结束,释放它锁住的数据;而对于外层In Place Element Structure来说,它内部的全部代码要运行结束,它才结束。
因而它们相互等待,造成了死锁。
Packed Project Libraries 2 –与Library的比较acked Project Library 从名字上来看,就是被包装好了的Project Library。
Project Library 是编程时候由程序员创建出来的。
比如下图这个工程,我在里面创建了一个叫做“My Algorithm Library.lvlib”的工程库。
它包含两个VI,其中一个是私有的。
Packed Project Library 并不是手工创建的,他是通过一个项目的生成规范,从Project Library 编译而来的。
比如上图的项目,我创建了一个Packed Library类型的生成规范。
Labview-学习笔记reference 死锁问题LabVIEW中的引用经常需要和“In Place Element Structure”配合使用。
In Place Element Structure 对一个引用的数据进行处理时,为了保证多线程安全,它会锁住引用指向的数据;其它线程若需对同一数据做操作,必须能这个In Place Element Structure中所有代码执行完毕才可,这样就避免了多线程读写同一内存数据所产生的竞争问题。
举例来说,下面这段程序的执行时间是1秒:而下面这段程序的执行时间则是2秒:因为第二段程序中的两个In Place Element Structure必须顺序执行。
有了“锁住”这个操作,就有不小心造成死锁的可能。
比如对于同一数据的引用,千万不能嵌套使用In Place Element Structure,否则就会死锁:Packed Project Library 并不是手工创建的,他是通过一个项目的生成规范,从Project Library 编译而来的。
比如上图的项目,我创建了一个Packed Library类型的生成规范。
我在这个生成规范中指定把“My Algorithm Library.lvlib”编译成Packed Project Library 。
编译的结果是在我指定的路径下生成了一个名为“My Algorithm Library.lvlibp”的文件。
它的后缀名仅比Packed Library多了一个字母p。
双击这个文件,可以打开它,看到他里面包含的VI:如果需要在其它项目中使用到这个Packed Project Library,我们可以直接把它加到另一个项目中去,下图是一个演示项目:Packed Project Library 看上去和Project Library 非常相似,用法也完全相同。
Packed Project Library 与Project Library•都是将功能相关的一组VI封装起来的方法;•库中的VI可以具有层次机构;•库中的VI都带有名字空间,名字空间是带有后缀名的库名;•都可以方便的放在项目管理器里使用尽管它们十分相似,Packed Project Library 与Project Library 相比,还是有一些明显区别的:•Packed Project Library 是通过编译生成的;•Packed Project Library 中的VI是编译后产生的,它们不能被修改;•Packed Project Library 包含有私有VI,但用户无法看到也不能使用它们;•Packed Project Library 把VI,.lvlib以及其它用到的文件都打成一个压缩包,用户在磁盘上就只能看到一个.lvlibp文件,看不到VI文件;•Packed Project Library 很适合作为最终产品发布给用户使用;•在项目中使用Packed Project Library 可以缩短编译时间,因为Packed Project Library 中的VI是已编译好的,不会再随项目编译一遍。
labview控制程序流程——labview事件结构1 事件结构及它的图形化表示法事件被用来通知用户有异步活动发生。
图形化语言的事件响应包括:用户界面事件、外部I/O 事件和程序其它部分的事件。
对事件的处理程序也被称为:事件驱动程序。
事件驱动程序可以分为若干个分支,每个分支处理不同的事件响应。
所以对事件的响应结果也可以控制程序的流程。
事件驱动机制来自于可视化的操系统,可视化操作系统对用户事件提供了简洁、有效的响应方式,最常见的事件来自于鼠标和键盘。
虚拟仪器借助于操作系统的事件处理机制实现了图形化语言的事件响应能力。
在没有引入事件结构之前,LabVIEW 是借助于轮询的方式来查询用户操作,由于轮询的方式会占用一定的CPU 资源,甚至可能遗漏事件,所以这种处理方式并非理想。
事件结构的出现避免了对CPU 资源的占用,同时也避免了事件的遗漏。
事件结构在函数选板》编程》结构子选板中可以找到,并可以将其直接拖拽到程序框图中,图形化表示的事件结构,参见下图。
图 1 图形化的事件结构与Case 结构和循环结构类似,事件结构也包含了一个主框架,这个框架内将用来放置事件处理的事件驱动程序代码。
如果事件处理任务众多,会有众多事件分支存在,在结构上类似Case 的多帧结构(选择器标签)。
当在程序框图上拖放一个事件结构时,我们只能看到上图所示的一帧已经预先注册的超时事件(Timeout),超时事件分支。
它具有定时延迟的基本功能(不包括While 循环),参见下图。
图 2 具有定时延迟的基本功能当然也可以采用另一种表示方法,参见下图。
图 3 利用事件结构内部节点获得中止时间通过这个例子也好理解内部节点中时间的含义(是事件响应的停止时间)。
超时事件超时事件是一种特殊的事件,当然也可以看成是默认的事件分支。
如果存在其它事件源时,超时事件完全可以被忽略或取消。
看下面一个例子。
图 4 仅有的两个事件之一超时事。
LabVIEW经典结构——组合动作执行模型
在LabVIEW应用程序开发中,广泛使用了一种高效的程序结构——组合动作执行模型。
该模型由While、Evnet(事件)、For、Case、enum(枚举)等向种结构和数据类型构成。
执行机理:面向对象的事件结构,响应前面板发生的针对控件的鼠标、键盘的动作,产生事件,并输出一个枚举数组,该数组作为For循环执行的索引,同时数组元素定义了执行的Case。
将各种事件响应进行分解为基本的动作单元,利用枚举数组定义出若干个由动作单元组合而成的动作序列,依据控件事件选择执行枚举数组,顺序完成对应的动作单元。
模型特点:重复利用各基本动作单元,增加代码复用率,程序更加简洁。
通过新建事件,可以定义任意组合的动作序列,灵活高效。
具有很强的模块化设计思想。
图1组合动作执行模型。
labview事件结构使用方法在LabVIEW中,事件结构是一种可以按照事件的发生改变程序流程的数据结构,可以通过人机互动或者事件干预的方式产生事件驱动,在LabVIEW中是一种常用的数据结构,下面我就来讲解一下其具体的使用方法。
一、事件结构的使用目的在LabVIEW中一个重要的概念就是数据流,我们在编程的时候可以来设置某些事件来对数据流进行干预,比如说单击鼠标产生事件,按下键盘按键等,这些都可以被当作为事件结构的条件,进而实现对程序的控制。
二、事件结构的创建方法1.在程序窗口中的空白处单击鼠标右键,在弹出的函数选板中选择<结构>子选板,然后再选择<事件结构>并将其拖到程序框图中即可。
2.最基本的事件结构是由<程序框架>、<子框图标识符>和<事件数据节点>组成。
3.在刚创建事件结构时,会自动的创建一个<超时端口>,<超时端口>用于连接一个数值指定等待事件的毫秒数,如果超过设定的时间没有发生事件的话,程序就会产生一个超时事件。
4.<事件数据节点>用于访问事件的数据值,可以单击节点中的数据项,然后在弹出的菜单中,选择<选择项>,可以进行选择访问哪个事件数据的成员。
5.在事件结构的边框上单击鼠标右键,在弹出的菜单中选择<添加事件分支>,即可完成子框图的添加。
三、对事件进行编辑1.换到要进行编辑的子框图中,在边框上单击鼠标右键,在弹出的快捷菜单中选择<编辑本分支所处理的事件>选项,打开<编辑事件>对话框。
2.在<编辑事件>界面中可以对相应的事件源和事件进行定义,在左侧的<事件说明符>下面点击<添加事件>或者<删除>即可相应的改变事件数量。
在<事件源>和<事件>两个子窗口中分别选中相应的对象,左侧的<事件说明符>下面就会出现两者的组合,点击<确定>,此子事件框图就可以完成编辑。
LABVIEW中的事件结构杂谈刚开始接触事件结构时觉得它很好用,所以很喜欢用,但也引起了一些问题,就是前面板很容易就被挂起来了,就是所前面板没有响应了,很郁闷。
之后就不敢用了,很多可以用事件结构的地方都只用CASE结构麻烦的代替了~~今天被师兄那么一指点,觉得完全是委屈了事件结构啊,之前事件结构引起的问题可以很容易的解决。
方法就是设置“超时”(之前一直觉得这个东西没用的):一般情况下,事件结构是会和while循环套用的,通过不断的循环来执行不同事件源激发的事件,但如果不设置超时,也没有事件源发生,那么while循环将一直等待事件的发生而不进行循环,这样就会使得事件结构外的其他程序也不能执行,可能造成的结果就是前面板本该有反应的地方(比如变量值的变化)没有了反应。
而如果设置了超时,比如设置为100(ms),意思就是每隔100ms如果没有事件发生就超时,进行一次循环,那么事件结构外的其他程序也就得到了执行。
总结一下:如果事件结构在while循环中,而事件结构之外又有其他的程序需要执行(可能不依赖于事件的发生),那么就应该设置超时。
在事件处理过程内,如何响应前面板命令控件的命令? 我发现,在一个事件内的处理过程完成之前,系统不能响应前面板的其他命令。
系统是在事件完成之后的等待时期才响应其他前面板命令事件。
编辑事件结构对话框的下边有一个: 锁定前面板在事件分支执行完毕前。
你可这个默认选中的选项取消了,就可以实现你的“在一个事件过程处理中途响应前面板的其他命令"功能。
LabVIEW事件结构使用LabVIEW图形化语言开发的应用程序界面是图形化用户操作界面,也称为:GUI (graphical user interface),它的作用是与操作者实现人机对话形式的互动操作。
这种对界面操作的互动响应在LabVIEW 6.1发布之前,只能通过“轮询(polling)”的方式来实现。
轮询的方式的缺点是:需占用一定的CPU资源(在没有事件发生时)和灵活性不好。
事件结构阮奇桢Event Structure 也是一种选择结构,程序根据发生的事件决定执行哪一个页面的程序。
此时,LabVIEW 的界面编写与Visual Basic 的界面程序有些类似。
一. 按照产出源来区分事件的种类按照事件的产生源来区分,LabVIEW有以下几种事件:图1:配置事件1.应用程序事件(<Application>),这类事件主要反映整个应用程序状态的变化,例如:程序是否关闭,是否超时等。
2.VI事件(<This VI>),这类事件反映当前VI状态的改变。
例如:当前VI是否被关闭,是否选择了菜单中的某一项等等。
3.动态事件(Dynamic),用于处理用户自己定义的或在程序中临时生成的事件。
4.区域事件(Pane)和分割线事件(Splitter)是LabVIEW 8中新添加的特性。
LabVIEW 8中,用户可以把一个VI的前面板分割成几份,这两类事件用来处理用户对某个区域或区域分割线的状态的改变。
图2:面板上划分区域5.控件事件(Control)是最常用的一种事件,用于处理某个控件状态的改变。
例如,控件值的改变,或者鼠标键盘的操作。
打开上述的“edit events”框,只要选定了某一个事件产生源,其相应的所有事件均排列在右侧events框中。
有时候,多个事件产生源会对同一个用户操作分别产生相应事件。
比如在某一控件上按下鼠标,区域事件和控件事件都会发出鼠标按下(Mouse Down)事件。
LabVIEW 按以下规则顺序产生不同的事件:键盘相关的事件(Key Down, Key Up, etc.)只在当前选中(Key Focused)的控件上产生;鼠标相关的事件(Mouse Down, etc.)按照从外向里的顺序发出。
例如,区域的鼠标按下事件先于控件的鼠标按下事件发出;结构的鼠标按下事件先于先于结构内控件的鼠标按下事件发出。
值改变事件按照从内向外的顺序发出。
LabVIEW技巧系列(一)——事件结构
事件结构,是LV编程结构的精髓所在。
它类似于单片机的中断功能,优
点在于不占用CPU资源。
比如按键按下串口发送数据,以及设置键盘快捷键
等等功能,事件结构比查询结构要节省很多系统资源。
下面我介绍一下利用事件结构的关键点,基础的自己去看帮助吧。
1,关于事件结构超时连线的问题:事件结构有一个超时事件的输入,当不连接时代表永不超时。
这点要十分注意,因为有时候你的事件就够会和其他结构放在一个while循环里,比如下图:
我们理想的情况是,其他服务程序正常循环运行(小灯闪烁),而鼠标按下后,处理事件结构。
但是如果这样写的话,由于事件结构永不超时,while循
环只会运行一次,只有当鼠标按键按下后,才会开始第二次循环。
这个程序的运行结果是,按一下鼠标,小灯变化一次。
要解决这个问题有两个办法:一个是给事件结构的延时输入处添加延时时间,比如5ms,这样循环就会5ms运行一次,不会影响其他服务程序的正常运行。
二个就是把其他服务程序放到另外一个while循环中,事件结构单独一个循环。
个人建议选择第二个方法。
2,关于事件结构软触发的问题:前面板有一个按钮,按下后触发很简单,
也很常用。
不过有时候要涉及到软触发的问题,就是利用程序(而不是前面板的控件)去触发一个事件。
先看下面这个例子:
“服务程序”软件改变软触发的值,我们的理想目标是,每次改变服务程序的
值为真时,标志小灯会改变一次。
但是实际程序运行结果是,无论按多少次,小灯都不变。
因为直接赋值只能改变变量的值,而不能引起次变量的事件触发。
labview的事件结构的用法
LabVIEW的事件结构是一种特殊的程序结构,它可以让程序在等待用户输入或系统事件时暂停执行,直到事件发生后再继续执行。
事件可以是用户交互、数据输入、系统消息等,都可以被事件结构捕捉。
使用事件结构可以增强程序的交互性和灵活性,使程序能够更好地响应用户操作和外部事件。
事件结构包含一个或多个事件框,每个事件框都可以捕捉一个特定类型的事件。
当事件发生时,事件结构会自动跳转到相应的事件框,执行相应的代码,然后等待下一个事件的到来。
事件结构还可以设置超时时间,当等待事件的时间超过设定的超时时间时,事件结构会自动退出等待状态,进行下一步操作。
LabVIEW的事件结构还支持多个事件的并发处理,不同的事件框可以同时处于等待状态,当事件发生时,相应的事件框会立即响应,执行相应的代码,而不影响其他事件框的等待状态。
在LabVIEW中,事件结构可以用于各种应用场合,比如图形界面、数据采集、通信等。
通过事件结构,程序可以更好地与用户交互,响应外部事件,增强程序的实用性和可靠性。
- 1 -。
labview的事件结构的用法LabVIEW是一款强大的图形化编程软件,具备强大的数据采集和处理的能力,广泛应用于自动化、监控、控制等领域。
其中,事件结构是LabVIEW中最常见的流程控制结构之一。
本文将围绕事件结构的用法进行详细阐述。
事件结构是LabVIEW中的一种流程控制结构,它的主要功能是在某个事件发生时,执行相关的代码。
在实际应用中,事件结构通常用于响应用户的输入、硬件设备的触发等事件。
具体来说,事件结构可以分为两个主要部分:事件源和事件处理程序。
首先,需要明确的是,事件结构的建立需要先确定事件源,也称为该事件的产生者。
常见的事件源包括面板上的控件、VI的输入和输出、硬件设备和文件等。
选择合适的事件源很关键,因为它决定了事件结构的执行时机。
其次,需要编写相应的事件处理程序,即在事件发生时,要执行的程序段。
LabVIEW提供了许多已经编写好的事件处理程序,也可以根据需要编写自己的事件处理程序。
事件处理程序一般包括以下几个基本步骤:读取事件数据、执行相应的操作、更新界面或数据等。
不同类型的事件处理程序细节略有不同,但总体逻辑相似。
接下来,我们来看一下事件结构的具体用法。
1.使用事件结构实现面板控件的响应使用事件结构可以实现对面板控件的响应。
例如,我们要在按下按钮时执行某个操作,只需要在事件结构中选择该按钮控件作为事件源,然后编写相应的事件处理程序即可。
这样,只要用户按下该按钮,就会自动触发相应的事件处理程序。
2.使用事件结构实现VI的响应除了对面板控件进行响应外,事件结构还可以实现对整个VI的响应。
在新建事件结构时,可以选择VI作为事件源,然后编写响应程序。
这样,只要该VI被调用,就会自动触发相应的事件处理程序。
3.使用事件结构实现硬件设备的响应通过LabVIEW,可以方便地实现与硬件设备的交互。
在新建事件结构时,可以选择硬件设备作为事件源,然后编写响应程序。
这样,当硬件设备产生特定的信号时,就会自动触发相应的事件处理程序。
LabVIEW事件结构编程事件驱动的编程允许用户通过前面板的操作,或是其他的异步事件来驱动LabVIEW程序的运行。
事件是一种异步的信号,告知PC有事情发生。
用户界面、外部I/O或是程序的一部分代码都有可能导致事件的发生。
使用事件结构可以实现仅当事件发生时,程序才需要响应,别的时候程序可以处理其他迚程或是其他的事件,事件结构相当于一种“中断”。
相对的,如果不使用事件结构,程序会以“轮询”的方式来检测事件的发生,但这样会大大消耗CPU的使用时间,不利于处理复杂、多线程的程序。
因此,事件结构允许将CPU的使用降低到最小,但又不牺牲与用户的交互性。
用户界面事件:鼠标点击、键盘操作等等外部I/O 事件:硬件定时、硬件触发、或是硬件出错等等。
其他程序事件:程序间的通讯等注:LabVIEW支持用户界面事件和程序事件而不支持外部I/O事件。
1. 事件结构典型的事件结构如图1所示。
事件结构包括一个或多个子程序框图,或事件分支,注意每当结构执行时,仅有一个子程序框图或分支在执行。
事件结构的执行过程是,一直等待直至某一事件分支的事件发生,然后执行相应事件分支从而处理该事件。
右键单击结构边框,可添加新的分支并配置需处理的事件。
为事件结构边框左上角的“超时”接线端连接一个值,以指定事件结构等待某个事件发生的时间(以毫秒为单位)。
默认为–1,即永不超时。
图 1事件结构用户界面事件分为消息事件和过滤事件两种。
a.消息事件消息事件指一个用户的行为已经发生,使用消息事件来反馈一个已经发生的事件,并且LabVIEW已经对它迚行了处理。
例如,“鼠标按下”就是一个消息事件,图2中的事件结构的分支程序实现了用户用鼠标点击停止按钮,按下后停止程序的功能。
这个事件是在用户释放鼠标以后LabVIEW迚行处理的。
图 2 消息事件b.过滤事件过滤事件在用户行为发生之后,LabVIEW处理该事件之前先告知用户,由用户来决定程序接下来如何处理事件,有可能处理的方式与默认的处理不同。
LabVIEW设计模式汇总本文归纳了LabVIEW中常用的几种设计模式,介绍了各种设计模式的特点及适用范围,并提供了每种设计模式对应的典型应用实例。
1 标准状态机1.1简介状态机(State Machine)是编程中经典的设计模式之一。
状态机对系统所有可能的状态进行罗列,在每个状态分支中执行该状态的代码,并指明系统要执行的下一个状态。
状态机能清晰和准确地完成与状态密切相关的任务。
1.2结构图1-1为典型的标准状态机结构。
系统包含“Initialize”,“Idle”,“Case1”,“Case2”,“Stop”五个状态;系统可以在“Initialize”中初始化系统参数,在“Idle”中专门做状态选择处理,“Case1”和“Case2”为用户自定义的状态分支,“Stop”状态使系统停止运行。
图1-1 标准状态机结构1.3要点(1)状态枚举常量该枚举常量包含了系统所有可能的状态,每次可以选择一个指定的状态。
(2)带移位寄存器的while循环状态机通过while循环上的移位寄存器传递下一个要执行的状态,每次循环只能执行一个条件分支。
(3)条件结构该条件结构的每个分支对应一个系统的可能的运行状态。
Tips:●可以将枚举常量设计为自定义控件类型。
当系统状态需要修改时,只需要修改一次“自定义控件”即可更新整个程序中所有的枚举常量。
●将枚举常量连接到条件结构的选择器接线端后,右击条件结构边框,选择“为每个值添加分支”,可以轻松地为条件结构实现分支配置。
1.4实例(1)情景:使用温度监控系统监测当前温度,当温度超过高温阈值时发出“高温警报”,当温度低于冷冻阈值时发出“冷冻警报”。
(2)代码:详见附件中的“标准状态机”项目文件。
图1-2 前面板设计图1-3 程序框图设计1.5小结标准状态的应用非常广泛,它的特点是:(1)系统的所有状态和转换条件都是可以提前预期设定的,而不是随机产生的;(2)系统一次只能执行一个状态,不适合做并行任务处理。
labview从⼊门到出家4--⽤事件结构实现运算功能使⽤事件结构可以快速定位响应界⾯的操作事件,如按下,拖动,双击的事件。
基本上我们所要实现的所有功能,都可以通过条件结构+事件结构去实现,⽐如后⾯进阶篇将会讲到的状态机就是通过条件结构和事件结构组成的。
⼀个好的状态机可以帮助我们搭建⼀个好的程序框架,这将⾮常有利于我们以后写⼀些⼤型程序。
在此前,我们先⽤之前的加减乘除运算熟悉⼀下事件结构。
1、同样的,按上⼀章节的操作,或者直接拷贝上⼀章的程序。
新建⼯程->新建calc主VI->新建⼦VI,这⾥把主VI打回原型,把之前的条件结构减掉(其实就是⽤事件结构代替⾥⾯的条件结构,但只是介绍事件结构的使⽤,不是说事件结构可以取代条件结构)。
2、添加事件结构我们可以看到事件结构的第⼀个默认事件是超时事件(⽬前只有⼀个事件),左上⾓那个沙漏状的是超时时间设定,相当于单⽚机⾥⾯的定时中断,我们后⾯可以右键新建⼀个数值常量⽤于设定超时时间。
如果没设定超时时间,则在没有其他事件产⽣或触发前,整个while循环就卡在超时事件这边等待超时事件的发⽣,因为没有设定超时时间,所以程序⼀直等待,不响应事件之外的其他操作。
只有⼀个超时事件3、添加“布尔”按键的事件,⿏标移到事件结构上⽅的事件显⽰图标,右键选择“添加事件分⽀”。
选择布尔,选择值改变,点击确定就添加了我们的布尔按键的事件了。
⿏标点击事件结构上⽅的⿊下三⾓,显⽰有超时和布尔值改变两个事件分⽀,我们选中布尔值改变的事件分⽀,在该分⽀添加相关的程序逻辑。
4、将上⼀次章条件结构中的程序直接拷贝或者重新编写⾄事件分⽀中5、运⾏程序试⼀下功能(后⾯会出⼀章讲程序调试操作,我们到时候可以⽤调试⼯具查看事件功能的响应情况)。
我们发现基本功能和上⼀章的⼀致,但是会发现⼀个问题,点击退出按键的时候界⾯不响应退出的功能。
这时因为while循环中我们添加的是事件结构,也就是程序只有识别到事件发⽣时,才会执⾏⼀次while循环,没事件发⽣的话,则不会运⾏其他操作,也就不响应按键的执⾏了。
LabVIEW程序设计模式(四)—状态机和事件结构的结合上两节分别解决了基本状态机的第(1~5)个问题,但是是否具备一种模式能够综合队列型状态机模式和用户界面事件型模式的优点呢?这样可以同时避免基本状态机的第(1~5)个问题。
答案是肯定的,本节将介绍如何将状态机与事件结构结合起来形成一种新的、稳定的模式。
状态机模式的基本构成元素是while 循环和case 结构,而事件结构模式的基本构成元素是while 循环和event 结构,因此新的模式应该由while 循环、case 结构和event 结构组成。
而while 循环的目的是为了保证程序的持续运行,因此必须在最外层,这样就只剩下了图20 所示的两种组合方式。
在第一种方式中,每次循环的运行需要经过一个事件结构才能够实现case 中各个分支的运行,那么到底需要多少个分支呢?一般而言不同的事件都会有不同的事件处理函数(这些函数可以在case 结构中共用),显示这是无法满足要求的,它从本质上而言仍然是一种事件结构。
在第二种方式中,程序的主体是一个状态机结构,不同的是在某一个状态分子中有一个事件结构。
我们可以回忆状态机模式中的空闲Idle 状态,这正是长时间占用CPU 资源的源头,如果在Idle 中加入一个事件结构后就有效地规避了这个问题。
图20 三种结构的组合方式因此图20 中的第二种结构综合了状态机和事件结构的优点,有效地克服了基本状态机的第(1~5)个问题。
此外,在【应用2_自动贩卖机】例程中,按钮1USD、2USD 和5USD 的作用是相同的,唯一不同的是它们的代表的币值不同。
如果我们希望系统共用币值相加这个功能,即当这三个按钮任何一个被按下后都调用同一个函数(该函数的功能是将系统中原来的货币值与新加入的币值相加得到新的值)。
这样,需要有一种途径把1USD、2USD 和5USD 代表的币值作为参数传递给函数。
图21 所示为带参数的状态机结构,在消息队列的状态机模式中,加入了一个变体型的变。
LabVIEW程序设计模式(四)—状态机和事件结构的结合LabVIEW程序设计2009-05-04 14:25:19 阅读497 评论0 字号:大中小订阅上两节分别解决了基本状态机的第(1~5)个问题,但是是否具备一种模式能够综合队列型状态机模式和用户界面事件型模式的优点呢?这样可以同时避免基本状态机的第(1~5)个问题。
答案是肯定的,本节将介绍如何将状态机与事件结构结合起来形成一种新的、稳定的模式。
状态机模式的基本构成元素是while循环和case结构,而事件结构模式的基本构成元素是while循环和event结构,因此新的模式应该由while循环、case结构和event结构组成。
而while循环的目的是为了保证程序的持续运行,因此必须在最外层,这样就只剩下了图20所示的两种组合方式。
在第一种方式中,每次循环的运行需要经过一个事件结构才能够实现case中各个分支的运行,那么到底需要多少个分支呢?一般而言不同的事件都会有不同的事件处理函数(这些函数可以在case结构中共用),显示这是无法满足要求的,它从本质上而言仍然是一种事件结构。
在第二种方式中,程序的主体是一个状态机结构,不同的是在某一个状态分子中有一个事件结构。
我们可以回忆状态机模式中的“空闲Idle”状态,这正是长时间占用CPU资源的源头,如果在Idle中加入一个事件结构后就有效地规避了这个问题。
图20 三种结构的组合方式因此图20中的第二种结构综合了状态机和事件结构的优点,有效地克服了基本状态机的第(1~5)个问题。
此外,在【应用2_自动贩卖机】例程中,按钮1USD、2USD和5USD的作用是相同的,唯一不同的是它们的代表的币值不同。
如果我们希望系统共用“币值相加”这个功能,即当这三个按钮任何一个被按下后都调用同一个函数(该函数的功能是将系统中原来的货币值与新加入的币值相加得到新的值)。
这样,需要有一种途径把1USD、2USD和5USD代表的币值作为参数传递给函数。
10、结构的使用条件结构条件结构是执行条件语句的一种方法。
这类似于文本编辑语言中常见的If…Then…Else语句。
它位于程序框图中,函数→编程→结构→条件结构。
如图所示:条件结构包含有两个或者更多的子框图,每一个子框图包含一段程序代码,由此对应一个程序分支。
多个子框图就像一摞卡片重叠在一起,任何时候只有一个是可见的,执行哪一个取决于于选择端子外部接口相连的某个整数,布尔数,字符串或者枚举指,用户也可以直接输入所有可能出现的值。
1.选择端口的输入值条件结构选择端口的输入值是由与它相连的输入控件对象决定的,数据类型可以是布尔量,整形,字符串型或者枚举型。
条件结构顶部中间是各分支的选择标识,它自动调整为输入的数据类型,可以在工具模板上使用标签工具直接键入单个数值或某个数据范围。
数值之间用逗号来分开,例如:“..0,2,4..10”表示选择条件为:≤0,2,4,5,6,7,8,9,10。
对于字符型和枚举型数值在条件标识上会自动加上双引号,当键入的选择器标识值与连接选择端口的数值类型不同时,选择器标识变为红色标识有错误。
如图:设置默认分支的方法是,选择一个分支结构,在快捷菜单中执行“本分支设置为默认分支”,它的作用是当选择端口的值与选择器标识值没有一个匹配时,就执行默认分支。
如图:2.条件结构的数据通道条件结构的数据通道就是数据的输入和输出端口。
将结构内外的端子相连后,边框上就会出现一个小矩形框,这就是数据通道,用于传输数据。
向条件结构的一个分支提供数据时,这个数据对于所有的分支都是有效的,也就是其他分支都可以使用这个输入数据。
条件结构的输出通道有些不同,当在一个分支中创建输出通道后,所有分支的同一位置都会出现一个白色小方框,它要求每一个分支都必须为这个通道予以连接,通道变为实心后程序才可以运行。
也可以在通道的快捷菜单中选定“未连线时使用默认”为没有连接的分支定义一个默认输出值,这时输出通道变为灰色。
如图:条件结构应用举例例一:该例的目的是检查一个数是不是正数,如果是就计算该数的平方根值,如果不是则发出警告。
LabVIEW事件结构的妙用
首先,我们回顾一下上期节目:LabVIEW网络讲坛乊悬案迷思中关于事件结构的几个重要知识点。
事件结构的基本组成部分:
事件结构五大基本组成部分
事件结构由——事件选择器、超时接线端、事件数据节点、事件过滤节点和动态事件接线端5个基本部分组成。
事件结构编程的3条黄金原则:
在使用LabVIEW事件结构迚行编程的时候,我们应该注意:1.不要将事件结构放置在while循环乊外,而应该放置在while循环的内部;2.不要在事件结构的内部使用循环处理事件,可选择采用生产者消费者结构,在生产者循环中放置事件结构,在消费者循环中处理事件;3.记得为事件结构添加一个单独处理停止按钮的分支。
遵守以上三条原则将使我们的程序更加健壮,避免在使用事件结构的时候出现前面板死锁等问题。
过滤事件与通知事件:
在LabVIEW中,以问号结束的事件被称为过滤事件,其余的事件被称为通知事件。
对于通知事件,程序可以感知事件的发生并且响应该事件,然后再处理在事件结构中定义的任务;而对于过滤事件,程序感知事件发生后,首先处理在事件结构中定义的任务,然后根据事件过滤节点的值(Discard?)来决定是否响应该事件或是否改变事件数据。
因此我们建议,在希望参与处理用户操作时使用过滤事件,因为过滤事件可以放弃事件或修改事件数据。
如果仅需要知道并响应用户执行的某一特定操作,则应使用通知事件。
在本期节目中,我们着重介绍动态注册事件的用法。
静态和动态两种事件注册模式:
静态注册指定了事件结构的每个分支具体处理哪些事件。
一旦VI开始运行,LabVIEW将自动注册这些事件,并且在VI运行的整个过程中无法改变事件结构所处理的事件。
而动态事件注册与VI服务器相结合,允许在程序运行时使用控件、VI或应用程序的引用来动态地指定和改变产生事件的对象。
动态注册在控制LabVIEW产生何种事件和何时产生事件等方面更为灵活。
Demo 1和Demo 2帮助大家更好地理解动态注册事件编程方法。
Demo 1:动态注册事件_阿拉丁神灯.vi
Demo概述:
在这个VI中,用严格自定义的方式将一个布尔类型的控件做出神灯的样子,并为这个布尔控件动态注册了”鼠标按下”的事件。
这个事件执行的任务是显示神灯神仙,并弹出一个对话框。
由于该事件采用的是动态注册的方式,所以可以通过一个按钮取消对该事件的注册。
并通过另一个按钮再次注册该事件。
这就是动态事件的使用效果,它可以在程序运行的过程中,动态地控制何时注册事件和注册什么样的事件。
程序实现:
1.当我们选择动态注册事件的时候,首先需要在程序框图上放置一个“注册事件”函数;该函数位于:函数面板》对话框与用户界面》事件》注册事件。
2.接下来,在“注册事件”函数的事件源输入端上连接一个引用,该引用可以是控件、VI或应用程序的引用。
在阿拉丁神灯的程序中,事件源就是神灯所对应的布尔控件,所以我们为注册事件函数连接该布尔控件的引用。
3.单击事件源的向下箭头,可以选择该引用对应注册事件,例如:鼠标按下、鼠标迚入、值改变等等。
调整“注册事件”函数的大小,还可以选择另一个事件,从而为一个或多个引用注册多个事件。
4.在程序框图上“注册事件”函数的右侧是一个While循环,在循环中放置一个事件
结构。
右键单击事件结构的边框,从快捷菜单中选择显示动态事件接线端。
动态
事件接线端的左侧与“注册事件”函数的事件注册引用句柄相连,右侧与“取消注册
事件”函数的事件注册引用句柄相连。
“取消注册事件”的作用是彻底停止对事件的
响应,并释放相应的内存资源。
5.接下来,我们需要编辑事件结构的分支,以处理动态事件。
应该注意的是,要将某个事件分支配置为可动态处理的注册事件,必须从动态列表中选择所需的事件源,而不能从控件列表或其它列表中选择。
在阿拉丁神灯的程序中,动态注册的“神灯:鼠标按下”事件分支,执行的操作就是:显示神灯神仙对应的图片控件,并弹出对话框,当对话框关闭时,图片也随乊隐藏起来。
6.那么程序又是如何取消动态注册事件的呢?让我们来看一下“取消注册”的事件分支:同样是放置一个“注册事件”函数,将事件注册引用句柄与动态事件接线
端连接起来,将一个“非法引用句柄常量”赋给事件源接线端(该常量位于文件I/O》文件常量》非法引用句柄常量),此时,前一个“注册事件”函数对应的动态注册
事件将被取消。
7.在事件被取消后,如何再次恢复该事件呢,让我们一起来看看“注册”分支中的代码。
同样是放置了一个“注册事件”函数,将事件注册引用句柄与动态事件接
线端连接起来,将神灯控件的引用连接到事件源接线端。
这样,在按下了注册按
钮乊后,该事件将被重新注册。
Demo2:动态注册事件_鼠标拖曳.vi
Demo概述:
我们知道,在一个VI运行的过程中,前面板上控件的位置是静止的,不能像VI没有运行时那样,可以通过鼠标的拖动来改变控件的位置。
而动态注册事件,就能在VI运行的过程中,用鼠标拖动前面板控件,让控件的位置将随着鼠标的位置而移动。
在VI的前面板,有三张扑克牌,它们是三个图片控件。
在VI运行的过程中,用鼠标拖动这些控件,它们的位置将发生改变。
程序实现:
1.首先,仍然是在循环的外部放置“注册事件”函数,通过下拉该函数,创建3个事件。
其中,“鼠标按下”后面带一个问号为过滤事件,“鼠标移动”和“鼠标释放”为通知事件。
“鼠标移动”的事件源是当前的vi,所以我们将一个“通用VI
引用”连接到它的事件源输入端;“鼠标按下”和“鼠标释放”的事件源是前面板上的所有控件,所以我们通过两个属性节点,得到了所有控件的引用数组,并连接到“鼠标按下”和“鼠标释放”输入端。
2.再来看事件结构中几个事件分支的实现,首先是“鼠标按下”过滤事件,在该分支中,我们通过事件数据节点“控件引用”来获知鼠标拖动的具体是哪个控件,并将该控件的引用传递给移位寄存器。
3.接下来,在“鼠标移动”的分支中,通过事件数据节点“坐标”获取鼠标的位置,并把该坐标值赋给“鼠标按下”的控件,从而达到控件被鼠标拖动的视觉效果。
4.最后,在“鼠标释放”的分支中,通过“非法引用句柄常量”取消对“鼠标移动”事件的注册,从而实现在鼠标释放后,控件的位置不再跟随鼠标发生变化。
在某些情况下,不使用动态注册事件,而使用过滤事件,也可以实现鼠标拖曳动态显示的前面板效果,通过Demo 3迚行说明。
Demo 3:过滤事件_鼠标拖曳显示波形.vi
Demo概述:
前面板上有一个树形控件,树形结构的最顶层是信号,下面是正弦波、方波、锯齿波、三角波四种类型。
运行这个VI,用鼠标拖动文字,放入波形图表,图表中则
显示相应的波形。
程序实现:
在程序中,我们用到了“拖曳开始”的过滤事件,和它对应的“数据”和“拖曳模式”两个事件过滤节点。
1.首先,用一个条件结构判断鼠标拖动的是哪种信号对应的字符串,已产生对应的波形数据。
由于事件过滤节点——“数据”定义的类型是簇数组,并且每个簇元素都是字符串和变体的组合,所以我们将波形数据转换为变体数据,并跟字符串“waveform”捆绑起来,通过事件过滤节点迚行传递。
2.在“波形图表:拖曳输入”分支中,判断拖曳到波形图表的是否是有效值,是则通过事件过滤节点接受;如果不是,则数据将被丢弃,而不做任何处理。
3. 在“波形图表:放置”分支中,依然是先判断放置到波形图表的是否是有效值,如果是,则通过“获取拖放数据”(该函数位于应用程序控制》获取拖放数据)将数据提取出来,在波形图表中显示。
如果数据无效,则丢弃不做任何处理。
总结
在本期的节目中,我们首先回顾了上期节目“事件结构乊谜”中的几个重要知识点。
然后,我们通过阿拉丁神灯和鼠标拖动扑克牌的两个范例程序,介绍了动态注册事件的用法。
当我们希望事件只发生在应用程序的某些部分,或在程序运行的过程中,可以动态改变发生事件的控件或VI时,就需要用到动态注册。
动态注册在控制LabVIEW产生何种事件和何时产生事件等方面更为灵活。
接下来,由鼠标拖动扑克牌引伸出鼠标拖动显示波形的应用,虽然该应用基于静态事件注册,而非动态注册;但过滤事件的巧妙使用,使得我们仍然可以获得动态的用户事件效果。
在LabVIEW事件结构的高级应用中,我们还会学习到用户自定义
事件、ActiveX事件以及.Net事件的使用方法,敬请关注。