在WinCC画面中存在四个脚本队列,分别是事件触发的VBS脚本、周期触发的VBS脚本、事件触发的C脚本、周期触发的C脚本。
事件触发脚本是指在对象的事件中编写的脚本,例如,按钮的按下事件,或者输出输入域的输出值改变触发的事件。
画面中周期触发的脚本,是指画面对象动态化属性的脚本,也就是写在画面对象属性中“动态”下的脚本,例如,下图所示为矩形对象的动态化脚本。
在对象动态化脚本中可以设置脚本的触发方式,支持事件触发(变量改变时触发)以及周期触发,如下图所示。经测试,这里的脚本(包括变量改变时触发的脚本)都属于周期触发的脚本。
不同队列里的脚本互不影响,相同队列里的脚本需要按顺序执行,当前面的脚本没执行完时,后面的脚本需要排队。
同一队列里的脚本需要排队
下面以一个示例来说明这个问题。在WinCC主画面中通过VBS来切换画面窗口中显示的画面,画面1显示在画面窗口中,如下图所示。
画面1中按钮按下的VBS脚本如下:
Dim tag5,I
Set tag5 = HMIRuntime.Tags("tag5")
For I=1 To 9000 ‘循环脚本大概需要花费10s
tag5.Write tag5.Value +1
Next
上面脚本大概需要10s才能执行完成。(说明,此处脚本没有实际意义,只是为了仿真长时间执行的脚本。)
主画面上两个画面切换按钮的VBS脚本:
ScreenItems("画面窗口1").PictureName="画面1" ‘在画面窗口中显示画面1
ScreenItems("画面窗口1").PictureName="画面2" ‘在画面窗口中显示画面2
切换到画面1并点击画面1上的按钮,如果在脚本执行完成之前点击切换画面2的按钮,画面并不会马上切换,而是要等到循环脚本执行完成后才能执行画面切换脚本。
总结:所有WinCC画面上的事件触发的VBS脚本都在一个队列内,按照先后顺序加入队列,队列按照先进先执行的原则来处理脚本。
同样,把画面中按钮的脚本改成C脚本:
int i;
while (i<9000)
{
SetTagDWord("tag5",i+1); //Return-Type: BOOL
i++;
}
把切换画面按钮改成C脚本:
SetPictureName(lpszPictureName,"画面窗口1","画面1");
SetPictureName(lpszPictureName,"画面窗口1","画面2");
执行情况和VBS相同。同样说明所有WinCC画面上的事件触发的C脚本也都在一个队列内。
画面中的VBS和C脚本是不同的队列
在上面的例子中画面1按钮脚本使用C脚本:
int i;
while (i<9000)
{
SetTagDWord("tag5",i+1); //Return-Type: BOOL
i++;
}
主画面中切换画面的按钮使用VBS脚本:
ScreenItems("画面窗口1").PictureName="画面1" ‘在画面窗口中显示画面1
ScreenItems("画面窗口1").PictureName="画面2" ‘在画面窗口中显示画面2
则可以在C循环脚本执行过程中正常通过VBS切换画面。
同样,画面1按钮脚本使用VBS脚本:
Dim tag5,I
Set tag5 = HMIRuntime.Tags("tag5")
For I=1 To 9000 ‘循环脚本大概需要花费10s
tag5.Write tag5.Value +1
Next
切换画面使用C脚本:
SetPictureName(lpszPictureName,"画面窗口1","画面1");
SetPictureName(lpszPictureName,"画面窗口1","画面2");
也可以在VBS循环脚本执行过程中正常通过C切换画面。
总结:画面中的事件触发的VBS脚本和C脚本是在不同的队列中,互不受影响。
事件触发和周期执行脚本在不同的队列
接着上面的例子,画面切换按钮还是使用VBS脚本,但把画面1上的循环脚本放到按钮的动态属性脚本中,如下图所示。
同时,脚本触发器设为10s,如下图所示。
此时在VBS循环脚本执行过程中,画面切换按钮同样可以通过VBS脚本来切换画面。
总结,WinCC画面中的事件触发的脚本和周期性触发的脚本是在不同的脚本队列。
结束语
通过这篇文档,我们学习了在WinCC画面中使用脚本要注意其工作的队列,脚本之间由于队列的队列可能会存在互相影响。掌握脚本所处的队列之后就可以避免脚本之间由于冲突造成的工作不正常现象。