执行队列的运行规则

当有多个相同的事件积木被触发时,它们会被添加到一个执行队列中,交由Scratch所制定的某种规则依次启动。

现在我们继续来思考,假如事件积木后面改为拼接多个指令,它们会按照什么顺序来执行呢?

我们可以先假设出两种不同的执行方式,然后对它们进行验证。

方式一,按照事件积木的启动顺序依次执行。

在这种方式中,事件积木的启动顺序就代表了它所在指令串的执行顺序。Scratch会先把事件一的所有指令执行完成,再开始执行事件二;把事件二的所有指令执行完成后,再开始执行事件三,依次类推。

方式二,多个指令串交叉执行。

在这种方式中,一个指令串每次只执行一个指令,然后按照事件积木的启动顺序,在所有指令串之间切换执行。Scratch会先依次执行事件一二三四中的第一个积木,再依次执行事件一二三四中的第二个指令,依次类推。

基本假设已经有了,现在就需要设计实验,动手来验证它们。往下继续阅读之前,你可以自己尝试着完成验证工作。

首先,还是先将小猫放置在舞台的中央。再建立一个列表,用来存储指令执行的先后顺序。

接着,给小猫添加三个指令串。需要注意的是,事件一的当绿旗被点击积木第一个被拖入编程区,事件二的当绿旗被点击积木第二个被拖入,事件三的当绿旗被点击积木第三个被拖入。

接下来就请你思考一下,当你点击绿旗按钮时,列表从上至下依次会存入哪些数据?

如果程序是按照前面假设的方式一执行:

  1. 先执行事件一的所有指令,此时列表中会加入两个事件一。
  2. 开始执行事件二的所有指令,此时列表中会再加入两个事件二。
  3. 开始执行事件三的所有指令,此时列表中会再加入两个事件三。

最终列表中的内容会像下图这样。

如果程序是按照方式二执行:

  1. 先依次执行事件一二三中的第一个指令,此时列表中会加入事件一、事件二,事件三。
  2. 依次执行事件一二三中的第二个指令,此时角色会向前移动,列表不会有变化。
  3. 依次执行事件一二三中的第三个指令,角色会切换下一个造型,然后往列表中加入事件二和事件三。
  4. 执行事件一中的第四个指令,往列表中加入事件一。

最终列表中的内容会像下图这样。

经过测试你会发现,实际的结果与之前设想的方式一完全一致。

使用执行队列来描述的话,队列中的指令串就是在按照下图的规则在运行(绿色表示正在执行,黄色表示等待执行)。

或许你现在已经举起双手,准备为自己发现的这个规则欢呼了。我想请你先把手放下来,继续思考一个问题。假如队列中的指令串真是按照上图的规则运行的话,我们的并行事件又应该如何解释呢?

例如,请你测试下图中的两个指令串。点击绿旗按钮以后,你会先看见小猫重复移动100次,再看见它重复切换造型100次吗?

只要你使用过并行事件,你就一定知道实际情况会是什么样。那么,是我们假设的方式一错了吗?

答案是,方式一并没有错,但它只说明了一部分规则。接下来,我们就尝试着根据你在并行事件中所看见的实际效果,继续来完善方式一的执行规则。

我们先来观察两次测试之间有什么区别?

在这两个测试中的一个主要区别是,第一次测试没有使用重复执行积木,第二次测试使用了重复执行积木。

使用重复执行积木的这两个指令串,程序会在它们之间来回切换执行。角色先移动一次,然后切换一次造型。接着重复移动第二次,然后第二次切换造型。接着又重复移动第三次,然后第三次切换造型,以此类推。似乎每当指令串执行完一次重复执行积木中的操作,就会暂停,交由下一个指令串运行。

按照新发现的规律,我们尝试着来修改一下方式一的运行规则。

1. 事件积木的启动顺序就代表了它所在指令串的执行顺序。

2. 如果指令串中没有重复执行积木,Scratch会把该指令串所有指令执行完成后,继续执行下一个指令串。

3. 如果指令串中有重复执行积木,则重复执行积木每重复一次,该指令串暂停,交由其他的指令串执行后,再继续下一次重复执行。

你可以想象重复执行积木的最后有一个暂停点,下图中左边的循环积木就等价于右边的模样。

接下来,还是利用实验来验证新规则是否正确。

注意我故意把两个重复执行积木的重复次数设置为不一样。实验之前请你还是先尝试着自己写出列表中存入的内容顺序,在与真实的实验结果进行对比。

使用执行队列来描述的话,队列中的指令串就是在按照下图的规则在运行(绿色表示正在执行,黄色表示等待执行)。

如果指令串中包含循环积木,每当执行到循环积木的暂停点时,该指令串重新变为黄色等待状态,交由下一个指令串继续执行。直到所有指令执行完成后,退出队列。

理解了上面的内容后,接下来就可以继续思考下一个问题。除了重复执行积木,还有哪些积木有暂停点(让当前指令暂停,交由其他指令运行)?

首先,控制分类中的三个重复执行积木都会有暂停点。

此外,控制分类中的两个等待积木也有暂停点。

你可以利用下图中的指令串进行实验。

实际上,等待(1)秒积木和等待<>积木的效果都可以利用重复执行积木来实现,你可以想象成等待积木就是利用重复执行积木自制而成。

下图中使用等待积木和重复执行积木的两种指令串,可以获得相同的结果。

其他的,还有运动分类中的在(1)秒内滑行到([随机位置])积木和在(1)秒内滑行到x:(0) y:(0)积木。它们同样类似于使用重复执行积木来实现。

声音分类中的播放声音([喵])积木、事件分类中的广播[消息1]并等待积木和舞台外观分类中的换成([背景1])背景并等待积木,它们类似于在换成([背景1])背景积木、播放声音([喵])积木和广播[消息1]积木后面增加了一个等待积木。

你同样可以进行一个简单的测试。

  1. 事件一开始执行第一次重复,列表中加入“事件一开始”,角色移动10步,列表中加入“事件一结束”,进入重复执行暂停点,程序暂停。
  2. 事件二开始执行第一次重复,列表中加入“事件二开始”,角色切换下一个造型,进入等待0秒暂停点,程序暂停。
  3. 事件一开始执行第二次重复,列表中加入“事件一开始”,角色移动10步,列表中加入“事件一结束”,进入重复执行暂停点,程序暂停。
  4. 事件二开始执行等待积木后指令,列表中加入“事件二结束”,进入重复执行暂停点,程序暂停。
  5. 事件一开始执行重复执行积木后指令,列表中加入“事件一终止”,程序结束。
  6. 事件二开始执行第二次重复,列表中加入“事件二开始”,角色切换下一个造型,进入等待0秒暂停点,程序暂停。
  7. 事件二开始执行等待积木后指令,列表中加入“事件二结束”,进入重复执行暂停点,程序暂停。
  8. 事件二开始执行重复执行积木后指令,列表中加入“事件二终止”,程序结束。

最终列表中的数据顺序就像这样。

你可以尝试着修改等待积木的时间,例如改为等待0.2秒。执行以后与上面的结果进行对比,你会发现列表中的数据顺序会稍有不同。

根据上面的实验结果,你可以继续将规则修改为下面这样。

1. 事件积木的启动顺序就代表了它所在指令串的执行顺序。

2. 如果指令串中没有暂停点积木,Scratch会把该指令串所有指令执行完成后,继续执行下一个指令串。

3. 如果指令串中有暂停点积木,则每次到达暂停点,该指令串暂停,交由其他的指令串执行后,再继续执行。

使用执行队列来描述的话,队列中的指令串就是按照下图的规则在运行(绿色表示正在执行,黄色表示等待执行)。

现在你已经知道了执行队列中多个指令的运行规则,下面我给你留下一个小练习。请你按照图片中的指令实现一个小碗接苹果的小游戏,然后利用指令的运行规则去分析一下,游戏中会有哪些问题?出现问题的原因是什么?如何修复这些问题?

最后,还有一个与执行队列相关的问题需要注意。

执行队列中,相同的指令串只能有一个。

上面这句话是在说,当一个事件积木被触发时,该事件积木所在的指令串将被加入执行队列中。在它执行完成,被移出执行队列之前,如果事件积木再次被触发,该指令串不会被再次加入队列,而是会出现下列两种情况之一:

第一种情况,该指令串会重新开始执行。

第二种情况,再次触发无效。只能等待该指令串执行完成,被移出执行队列之后,才能重新触发。

请你利用下图的指令串进行测试。快速的连续点击绿旗按钮,看看会出现情况一还是情况二?

接着,请你将当绿旗被点击积木替换为其他的事件积木,看看哪些事件积木属于第一种情况,哪些事件积木属于第二种情况。

在了解了执行队列的运行规则之后,我不知道你心里面会不会有这样的疑问。为什么重复执行积木的最后会有一个暂停点?有没有什么方法可以让重复执行积木不暂停呢?

Last Updated:
Contributors: lanheixingkong