执行队列的运行规则
当有多个相同的事件积木被触发时,它们会被添加到一个执行队列中,交由Scratch所制定的某种规则依次启动。
现在我们继续来思考,假如事件积木后面改为拼接多个指令,它们会按照什么顺序来执行呢?
我们可以先假设出两种不同的执行方式,然后对它们进行验证。
方式一,按照事件积木的启动顺序依次执行。
在这种方式中,事件积木的启动顺序就代表了它所在指令串的执行顺序。Scratch会先把事件一的所有指令执行完成,再开始执行事件二;把事件二的所有指令执行完成后,再开始执行事件三,依次类推。
方式二,多个指令串交叉执行。
在这种方式中,一个指令串每次只执行一个指令,然后按照事件积木的启动顺序,在所有指令串之间切换执行。Scratch会先依次执行事件一二三四中的第一个积木,再依次执行事件一二三四中的第二个指令,依次类推。
基本假设已经有了,现在就需要设计实验,动手来验证它们。往下继续阅读之前,你可以自己尝试着完成验证工作。
首先,还是先将小猫放置在舞台的中央。再建立一个列表,用来存储指令执行的先后顺序。
接着,给小猫添加三个指令串。需要注意的是,事件一的当绿旗被点击积木第一个被拖入编程区,事件二的当绿旗被点击积木第二个被拖入,事件三的当绿旗被点击积木第三个被拖入。
接下来就请你思考一下,当你点击绿旗按钮时,列表从上至下依次会存入哪些数据?
如果程序是按照前面假设的方式一执行:
- 先执行事件一的所有指令,此时列表中会加入两个事件一。
- 开始执行事件二的所有指令,此时列表中会再加入两个事件二。
- 开始执行事件三的所有指令,此时列表中会再加入两个事件三。
最终列表中的内容会像下图这样。
如果程序是按照方式二执行:
- 先依次执行事件一二三中的第一个指令,此时列表中会加入事件一、事件二,事件三。
- 依次执行事件一二三中的第二个指令,此时角色会向前移动,列表不会有变化。
- 依次执行事件一二三中的第三个指令,角色会切换下一个造型,然后往列表中加入事件二和事件三。
- 执行事件一中的第四个指令,往列表中加入事件一。
最终列表中的内容会像下图这样。
经过测试你会发现,实际的结果与之前设想的方式一完全一致。
使用执行队列来描述的话,队列中的指令串就是在按照下图的规则在运行(绿色表示正在执行,黄色表示等待执行)。
或许你现在已经举起双手,准备为自己发现的这个规则欢呼了。我想请你先把手放下来,继续思考一个问题。假如队列中的指令串真是按照上图的规则运行的话,我们的并行事件又应该如何解释呢?
例如,请你测试下图中的两个指令串。点击绿旗按钮以后,你会先看见小猫重复移动100次,再看见它重复切换造型100次吗?
只要你使用过并行事件,你就一定知道实际情况会是什么样。那么,是我们假设的方式一错了吗?
答案是,方式一并没有错,但它只说明了一部分规则。接下来,我们就尝试着根据你在并行事件中所看见的实际效果,继续来完善方式一的执行规则。
我们先来观察两次测试之间有什么区别?
在这两个测试中的一个主要区别是,第一次测试没有使用重复执行积木,第二次测试使用了重复执行积木。
使用重复执行积木的这两个指令串,程序会在它们之间来回切换执行。角色先移动一次,然后切换一次造型。接着重复移动第二次,然后第二次切换造型。接着又重复移动第三次,然后第三次切换造型,以此类推。似乎每当指令串执行完一次重复执行积木中的操作,就会暂停,交由下一个指令串运行。
按照新发现的规律,我们尝试着来修改一下方式一的运行规则。
1. 事件积木的启动顺序就代表了它所在指令串的执行顺序。
2. 如果指令串中没有重复执行积木,Scratch会把该指令串所有指令执行完成后,继续执行下一个指令串。
3. 如果指令串中有重复执行积木,则重复执行积木每重复一次,该指令串暂停,交由其他的指令串执行后,再继续下一次重复执行。
你可以想象重复执行积木的最后有一个暂停点,下图中左边的循环积木就等价于右边的模样。
接下来,还是利用实验来验证新规则是否正确。
注意我故意把两个重复执行积木的重复次数设置为不一样。实验之前请你还是先尝试着自己写出列表中存入的内容顺序,在与真实的实验结果进行对比。
使用执行队列来描述的话,队列中的指令串就是在按照下图的规则在运行(绿色表示正在执行,黄色表示等待执行)。
如果指令串中包含循环积木,每当执行到循环积木的暂停点时,该指令串重新变为黄色等待状态,交由下一个指令串继续执行。直到所有指令执行完成后,退出队列。
理解了上面的内容后,接下来就可以继续思考下一个问题。除了重复执行积木,还有哪些积木有暂停点(让当前指令暂停,交由其他指令运行)?
首先,控制分类中的三个重复执行积木都会有暂停点。
此外,控制分类中的两个等待积木也有暂停点。
你可以利用下图中的指令串进行实验。
实际上,等待(1)秒积木和等待<>积木的效果都可以利用重复执行积木来实现,你可以想象成等待积木就是利用重复执行积木自制而成。
下图中使用等待积木和重复执行积木的两种指令串,可以获得相同的结果。
其他的,还有运动分类中的在(1)秒内滑行到([随机位置])积木和在(1)秒内滑行到x:(0) y:(0)积木。它们同样类似于使用重复执行积木来实现。
声音分类中的播放声音([喵])积木、事件分类中的广播[消息1]并等待积木和舞台外观分类中的换成([背景1])背景并等待积木,它们类似于在换成([背景1])背景积木、播放声音([喵])积木和广播[消息1]积木后面增加了一个等待积木。
你同样可以进行一个简单的测试。
- 事件一开始执行第一次重复,列表中加入“事件一开始”,角色移动10步,列表中加入“事件一结束”,进入重复执行暂停点,程序暂停。
- 事件二开始执行第一次重复,列表中加入“事件二开始”,角色切换下一个造型,进入等待0秒暂停点,程序暂停。
- 事件一开始执行第二次重复,列表中加入“事件一开始”,角色移动10步,列表中加入“事件一结束”,进入重复执行暂停点,程序暂停。
- 事件二开始执行等待积木后指令,列表中加入“事件二结束”,进入重复执行暂停点,程序暂停。
- 事件一开始执行重复执行积木后指令,列表中加入“事件一终止”,程序结束。
- 事件二开始执行第二次重复,列表中加入“事件二开始”,角色切换下一个造型,进入等待0秒暂停点,程序暂停。
- 事件二开始执行等待积木后指令,列表中加入“事件二结束”,进入重复执行暂停点,程序暂停。
- 事件二开始执行重复执行积木后指令,列表中加入“事件二终止”,程序结束。
最终列表中的数据顺序就像这样。
你可以尝试着修改等待积木的时间,例如改为等待0.2秒。执行以后与上面的结果进行对比,你会发现列表中的数据顺序会稍有不同。
根据上面的实验结果,你可以继续将规则修改为下面这样。
1. 事件积木的启动顺序就代表了它所在指令串的执行顺序。
2. 如果指令串中没有暂停点积木,Scratch会把该指令串所有指令执行完成后,继续执行下一个指令串。
3. 如果指令串中有暂停点积木,则每次到达暂停点,该指令串暂停,交由其他的指令串执行后,再继续执行。
使用执行队列来描述的话,队列中的指令串就是按照下图的规则在运行(绿色表示正在执行,黄色表示等待执行)。
现在你已经知道了执行队列中多个指令的运行规则,下面我给你留下一个小练习。请你按照图片中的指令实现一个小碗接苹果的小游戏,然后利用指令的运行规则去分析一下,游戏中会有哪些问题?出现问题的原因是什么?如何修复这些问题?
最后,还有一个与执行队列相关的问题需要注意。
执行队列中,相同的指令串只能有一个。
上面这句话是在说,当一个事件积木被触发时,该事件积木所在的指令串将被加入执行队列中。在它执行完成,被移出执行队列之前,如果事件积木再次被触发,该指令串不会被再次加入队列,而是会出现下列两种情况之一:
第一种情况,该指令串会重新开始执行。
第二种情况,再次触发无效。只能等待该指令串执行完成,被移出执行队列之后,才能重新触发。
请你利用下图的指令串进行测试。快速的连续点击绿旗按钮,看看会出现情况一还是情况二?
接着,请你将当绿旗被点击积木替换为其他的事件积木,看看哪些事件积木属于第一种情况,哪些事件积木属于第二种情况。
在了解了执行队列的运行规则之后,我不知道你心里面会不会有这样的疑问。为什么重复执行积木的最后会有一个暂停点?有没有什么方法可以让重复执行积木不暂停呢?