TCL vwait和预期之后呢?(tcl vwait and after not as expect

2019-10-19 21:45发布

我还是新的TCL,不要用它多,主要是在原有代码。 我无法用一个代码,并通过简化它,我得到了下面的代码。 在第二个“后”我有一个代码,有时需要更长的时间,有时远不止“之后的”第一速度更快。 我想我的代码进行每当其中一方的完成,忽视了其他。 然而,我的vwait总是等待“之后的”最新的我。

global tkf
set tkf b
puts "ini: $tkf"

# wait 7 seconds, then set tkf
set aid7 [after 7000 set tkf Y7]
puts "7: $tkf ($aid7)"

# wait 4 seconds, then wait 15 seconds, then set tkf
after 4000 {
  puts "will wait 15s"
  after 15000
  puts "waited, will set tkf 4"
  set tkf Y4
}
puts "4: $tkf"

vwait tkf
puts "vwait $tkf"

puts "end"

我希望它可以触发我vwait在7秒,然后继续。 但是,这是输出I得到:

E:\>tclsh vwait_test.tcl
ini: b
7: b (after#0)
4: b
will wait 15s
waited, will set tkf 4
vwait Y4
end

这意味着它在等待15秒,触发了设置TKF第二个代码。 我认为这将输出:

will wait 15s
vwait Y7
end

我不知道这是为什么它的行为或如何改变它,我不能让在文档页面的任何提示。 我会很感激,如果有人可以解释这种行为对我来说,和如何得到我想要的东西。 然后,我可以使其适应自己的代码。

Answer 1:

对于文档和将来参考的缘故,我张贴什么是基于通过施伦克和Bryan Oakley的评论我的理解发生的事件的扩大解释。 谢谢你俩。

after的命令不会在后台睡觉要在那个时候触发。 相反,它被保存在一个被称为“ 事件循环 ”的结构,并且当一些特定的命令被称为将只被执行,导致要处理的事件循环的命令。

下面是在代码中发生的事情:首先,它增加了after 7000码( set tkf Y7事件循环 ,为7秒后执行。 如果/ 事件循环被触发时,这只会被执行,什么时候会检查7秒条件。

然后,它增加了after 4000块到事件循环 ,也没有执行它。

然后到达vwait 。 此命令将触发事件循环 ,但并没有什么,现在要执行,所以它什么都不做。 因为vwait将继续运行事件循环直到变量的变化,主要的代码将无法前进。 相反, vwait仍将重复事件循环 ,直到事情发生。 但什么也没有发生在第4秒。 最后,在4秒钟后, 事件循环注意到在after 4000块已准备好执行。 因此, 事件循环执行的全部该块。

after 4000块将输出消息,睡眠15秒。 此时,主代码没有运行,因为它在等待vwait 。 而vwait正在运行的事件循环 ,现在正等待,因为事件循环中执行的事件; 事件循环运行这个块,其执行睡眠。 一旦15秒已经过去了,我们仍然继续块内,打印另一消息,并设置TKF set tkf Y4 。 在此之后,该块就完成了。

事件循环仍然有一个悬而未决的情况下,它可以运行,在after 7000 ,他们的条件不成立的最后一次事件循环检查,但如果事件循环现在检查的话将得到满足。 然而,当块运行完毕后,将vwait条件被满足。 这意味着, 事件循环就不会移动到下一个事件,因此将不执行after 7000 ,控制将返回到其主代码puts "vwait $tkf"

事情往往并行运行,始终只有一个线程。 的“ 事件循环 ”是平行结构,但它不会独立运行。 这意味着它不可能让我想+ vwait后使用的是什么。 我想在我的主代码进行取完第一个运行的印象是,他们在并行运行之后。 但是,完成第一永远是最先开始运行,因为他们不并行运行。 另外,我的解释,即vwait总是等待最新的“后”是错误的。 实际上,它只是在等待“后”是最短的。

现在就找到一个替代方案,可能与线程...: - /



Answer 2:

它已经有一段时间,因为我已经钻研这个深入TCL,但它看起来像你把整个应用程序15秒入睡4秒钟后。 当你这样做after 15000 ,没有任何东西可以发生15秒,因为TCL是单线程的。

要有点更清晰:有之间的差异after Xafter X {script} 。 前者是一样的“休眠”命令 - 程序字面上暂停的时间量。 后者,而不是睡觉,安排一些代码,在未来的某一时刻运行。

这是记录在后手册页。 这里有一个相关的报价:

MS后 MS必须是一个整数,以毫秒为单位的时间。 该命令休眠毫秒毫秒,然后返回。 而命令正在睡觉的应用程序不响应事件。

以上是从取http://tcl.tk/man/tcl8.5/TclCmd/after.htm#M5

在此背景下,“事件”包括安排与任何其他脚本after

该段紧跟在手册页:

之后毫秒?脚本脚本脚本...? 在这种形式的命令立即返回,但它安排稍后执行的Tcl命令毫秒毫秒为事件处理。 该命令将只执行一次,在给定的时间。 延迟命令由以相同的方式与concat命令连接所有脚本的参数形成。 该命令将在全局级别(任何Tcl过程的上下文之外)来执行。 如果在执行延迟命令,则背景误差将通过与插补bgerror登记的命令中报告错误发生。 该命令之后返回一个可以用于使用后取消取消延迟命令的标识符。



文章来源: tcl vwait and after not as expected?
标签: tcl