tcl vwait 和之后不符合预期? [英] tcl vwait and after not as expected?

查看:39
本文介绍了tcl vwait 和之后不符合预期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 TCL 还是个新手,用得不多,主要是在遗留代码中.我遇到了代码问题,通过简化它,我得到了下面的代码.在第二个之后"中,我的代码有时需要更长的时间,有时比​​第一个之后"更快.我希望我的代码在其中任何一个完成时继续运行,而忽略另一个.但是,我的 vwait 总是在等待我拥有的最新之后".

I am still new to TCL, don't use it much, mostly in legacy code. I'm having trouble with a code, and by simplifying it I got the code below. In the second "after" I have a code that sometimes takes longer, sometimes goes faster than the first "after". I want my code to proceed whenever either of them finishes, ignoring the other. However, my vwait is always waiting for the latest "after" I have.

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"

我希望这会在 7 秒时触发我的 vwait,然后继续.但这是我得到的输出:

I would expect this to trigger my vwait at 7 seconds, and proceed. But this is the output I get:

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 的第二个代码.我以为它会输出:

Which means it waited the 15 seconds and triggered the second code that sets tkf. I thought it would output:

will wait 15s
vwait Y7
end

我不知道为什么这是它的行为或如何更改它,而且我无法在文档页面上获得任何提示.如果有人可以向我解释这种行为以及如何获得我想要的东西,我将不胜感激.然后我可以将其调整为我自己的代码.

I have no idea why this is its behaviour or how to change it, and I couldn't get any hints at the documentation pages. I'd appreciate if someone can explain this behaviour to me, and how to get what I want. Then I can adapt it to my own code.

推荐答案

为了文档和未来参考,我根据 schlenk 和 Bryan Oakley 的评论,根据我的理解发布了对正在发生的事情的扩展解释.谢谢两位.

For the sake of documentation and future reference, I'm posting an expanded explanation of what is happening from what I understood based on comments by schlenk and Bryan Oakley. Thank you both.

带有命令的 after 不是在后台休眠的时候会被触发.相反,它保存在一个名为事件循环"的结构中,并且只有在调用某些特定命令时才会执行,这些命令会导致事件循环被处理.

The after with a command is not sleeping in the background to be triggered at that time. Instead, it is saved in a structure called "event loop", and will only be executed when some specific commands are called, commands that cause the event loop to be processed.

这是代码中发生的事情:首先,它将after 7000 代码(set tkf Y7)添加到事件循环,7秒后执行.这只会在事件循环被触发时/当它检查7秒条件时执行.

Here is what is happening in the code: First, it adds after 7000 code (set tkf Y7) to the event loop, to be executed 7 seconds later. This will only be executed if/when the event loop is triggered, when it will check the 7 seconds condition.

然后将after 4000块添加到事件循环中,同样不执行.

Then it adds the after 4000 block to the event loop, also without executing it.

然后它到达vwait.这个命令会触发事件循环,但是现在没有什么可以执行的,所以它什么都不做.因为vwait 会一直运行事件循环直到变量改变,所以主代码不会向前移动.相反,vwait 将继续重复事件循环,直到发生某些事情.但是在前 4 秒内什么也没有发生.最后,在 4 秒后,事件循环注意到 after 4000 块已准备好执行.因此,事件循环会完整地执行该块.

Then it reaches the vwait. This command will trigger the event loop, but there is nothing to be executed now, so it does nothing. Because vwait will keep running the event loop until the variable changes, the main code will not move forward. Instead, vwait will remain repeating the event loop until something happens. But nothing happens in the first 4 seconds. Finally, after 4 seconds, the event loop notices that the after 4000 block is ready to execute. So, the event loop executes that block in its entirety.

after 4000 块将打印一条消息并休眠 15 秒.此时,主代码没有运行,因为它在等待 vwait.而vwait 正在运行事件循环,现在正在等待,因为事件循环找到了要执行的事件;事件循环正在运行这个块,它正在执行睡眠.一旦 15 秒过去了,我们仍然在块内继续,打印另一条消息并使用 set tkf Y4 设置 tkf.之后,块就完成了.

The after 4000 block will print a message and sleep for 15 seconds. At this point, the main code is not running because it's waiting for vwait. And vwait was running the event loop, and is now waiting because the event loop found an event to execute; the event loop is running this block, which is executing a sleep. Once 15 seconds have passed, we proceed still within the block, printing another message and setting tkf with set tkf Y4. After that, the block is finished.

事件循环还有一个可以运行的待处理事件,after 7000,它的条件在上次事件循环时没有满足em> 检查它,但如果 事件循环 现在检查它会被满足.但是,当块完成运行时,满足 vwait 条件.这意味着事件循环不会移动到下一个事件,因此它不会执行after 7000,并且控件将返回主代码并带有<代码>放置vwait $tkf".

The event loop still have one pending event that it could run, the after 7000, whose condition was not met the last time the event loop checked it but would be met if the event loop checked it now. However, when the block finished running, the vwait condition was met. That means the event loop will not move on to the next event, and therefore it will not execute the after 7000, and the control will return to the main code with its puts "vwait $tkf".

事物永远不会并行运行,并且始终只有一个线程.事件循环"是一个并行结构,但它不是独立运行的.这意味着不可能使用 after+vwait 来制作我想要的东西.我想在先完成运行后继续执行我的主代码,给人的印象是它们是并行运行的.但最先完成的永远是最先开始运行的,因为它们不是并行运行的.另外,我认为 vwait 总是在等待最新的之后"的解释是错误的.其实只是在等待最短的之后".

Things are never run in parallel, and there's always only one thread. The "event loop" is a parallel structure, but it doesn't run independently. This means it's impossible to make what I want using after+vwait. I wanted to proceed in my main code after whichever finished running first, under the impression that they were running in parallel. But the first to finish will always be the first to start running, because they don't run in parallel. Also, my interpretation that vwait was always waiting for the latest "after" was wrong. Actually, it's just waiting for the shortest "after".

现在寻找替代方案,可能是使用线程... :-/

Now on to find an alternative, probably with threads... :-/

这篇关于tcl vwait 和之后不符合预期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆