一些初学LV的网友们近期发给我的邮件中多次谈到WHILE循环的一些问题,这些问题虽然很常见,但是是根本性的问题,原因在于这些问题之所以不容易理解,是因为刚刚接触LV,很难理解或者经常忽视了“数据流”的问题。

首先简要回顾一下WHILE循环的基本概念和特点,然后重点回复网友们有关WHILE循环的问题。

几乎所有有关LV的书籍中都把WHILE结构与C语言的DO WHILE循环相提并论 ,其实二者之间是存在很大差别的,其根本区别在于LV是基于数据流驱动的,而C语言则不是。
DO WHILE循环可以保证循环至少运行一次,LV中的WHILE结构也是如此,这是二者之间的共同点。C语言中的WHILE结构如下所示:

do{
// do sth
}while(condition)

我们需要特别注意的是,C语言中DO WHILE循环判断循环条件是在循环中所有语句执行之后,简单地说就是“先运行,后判断”,LABVIEW中的循环结构则不然,这导致了很多LV初学者很难理解LV中WHILE循环的一些特殊现象。

1、可以同时运行多个WHILE循环结构。
同时运行多个WHILE循环结构在C语言中是比较麻烦的,必须开辟多个线程,而LABVIEW是自动多线程的。LABVIEW不仅可以同时并行运行多个WHILE结构,甚至在每个while循环中可以同时运行多个数据流程。
多了同时运行的WHILE循环可以分成两类:
一类是一个VI中多个同时运行的WHILE循环。多个WHILE循环在同一程序框图中。
另一类是每个子VI拥有各自的WHILE循环,此时多个WHILE循环同时工作相当于WINDOWS的多窗口运行。

2、每个循环中必须增加延时函数,释放系统控制权。
如果在循环中没有延时类函数,将导致WHILE循环独占CPU,CPU占用率很快达到100%。

3、仅运行一次的WHILE循环+未初始化的移位寄存器。这就是著名的LV2(功能)全局变量。
 

下面解释一下网友的问题:

问题一、WHIEL循环中,假如等待函数设置为10秒(10000),在2秒时按下停止按钮,过了8秒循环仍然不能停止,这是为什么。

我们先看看C语言中,DO WHILE循环+延时函数的情形。
do{
//do sth
Sleep(10000);//有些编译器使用Delay()函数,效果相同,目的延时
while(!Stop)
上面的程序中,程序必须保证从开始延时至结束延时为10秒中,其中任意时刻停止为TRUE,WHILE循环实际工作时间为10秒。
LV中类似的程序框图如下图所示:
 
Picture
无论我们在循环启动10秒内任意时刻按下STOP按钮,WHILE循环经历的时间都是20秒。很显然这不是一个简单的DO WHILE循环,C语言中,同样的情况WHILE循环仅执行了一次,而LV中的WHILE循环却执行了2次,导致两次调用WAIT函数,延时20秒。
二者之间的区别在于检查循环条件的时刻。C语言中的DO WHILE循环之在循环结束时检查循环条件的,LV中的WHILE循环则不然。在循环开始时,等待函数与检查STOP按钮的值是同时发生的。

LV是数据流驱动的,一段框图的运行与否在于它的输入端子是有数据流动进来。循环开始时,由于WHILE循环条件端子上,STOP按钮的值直接流入,所以开始时就判断结束条件。由于开始时STOP为FALSE,此时决定了本次循环结束后,还要进行下一次循环。在读取结束条件的同时,WAIT函数开始延时10秒。

在延时10秒过程中,我们按下了停止按钮。STOP按钮需要LV回读时,才会自动恢复,我们可以看到,在10秒结束前,STOP一直处于按下状态。

WAIT函数等待10秒完成后,此时进入第二个循环,同样检查结束条件,此时停止按钮按下,下一个循环不再执行,但是此时等待函数第二次运行,等待10秒。两次运行等待函数,导致最后延时20秒钟。

回过头来,我们能否使LV中的WHILE循环真正像C语言中的DO WHILE一样运行那,我们只要改变LV中WHILE循环读取结束条件的时刻就可以实现了,如下图所示。
 
Picture
我们只要在10秒内按下停止按钮,则循环经历的时间为10秒,同上面C语言的DO WHILE循环功能完全相同了。原因在于我通过顺序结构,强行改变了读取STOP的时刻,即等待结束后读取结束条件。由于此时STOP为TRUE,所以下一次循环不再执行,退出。
上面我解释了延时为什么执行了两次的问题,实际上我们根本就不需要一个长时间延时的WHILE循环。对于一个几秒、几分钟、甚至几个小时才执行一次的需求,根本不需要创建一个独立的WHILE循环。
比如每分钟执行一次的程序,一个WHILE循环的延时为100毫秒,则可以对这个循环进行计数,当循环次数为60*10的整数倍时,就是经历了每个分钟的时刻。
 
问题二:为什么在WHILE循环中使用事件结构时,停止按钮需要按两次才能结束?

这个问题的出现实际上原因于问题一相同。

Picture
事件结构的特点是:一旦运行则处于等待状态。一旦有事件发生,则响应事件后,结束事件结构。

首次循环开始时,由于STOP为FALSE,开始时判断循环条件,则下次依然要进行循环。本次循环运行中,事件结构处于等待事件中。
循环运行过程中,按下STOP.则事件结构响应事件后立即结束,同时循环结束条件为TRUE,不再进入下一个循环。但是如同问题一一样,我们依然要执行第二次循环,因此,事件结构处于等待中,再按下STOP,又产生新的值变化事件,循环结束。

解决这个问题有两个方法:

一、如同问题一一样,强行规定读取STOP的时刻,把STOP放置在STOP值变化事件分支中。

Picture
二:使用TIMEOUT超时事件,TIMETOUT导致事件不断发生,因此可以自动触发事件结构,结束循环。
 
Picture
推荐使用把读取STOP放置在STOP值变化事件分支中。

上面我详细第介绍了WIHILE循环结构中的两个常见问题,希望能解释的清楚。
 
 





Leave a Reply.