在此Coundown计时器中取消延迟命令时,是否有种族条件?
我已经实现了一个具有“重置”按钮来取消倒计时的倒计时计时器:
set LAUNCHTIME 5
set message $LAUNCHTIME
set afterId {}
proc countdown {remainingSeconds} {
global afterId message
# **
if {$remainingSeconds > 0} {
set message $remainingSeconds
# **
set afterId [after 1000 [list countdown [expr {$remainingSeconds - 1}]]]
} else {
set message "Takeoff!"
.start configure -state normal
}
}
label .message -textvariable message
button .start -text Start -command {
.start configure -state disabled
countdown $LAUNCHTIME
}
button .reset -text Reset -command {
# Reset timer, message, and button.
after cancel $afterId ;# <- XXX: Could this cause a race condition?
set message $LAUNCHTIME
.start configure -state normal
}
grid .message
grid .start
grid .reset
grid anchor . center
这就是按下“启动”按钮时的外观:
是否可能会有可能的种族条件。重置“倒计时发生时按下按钮?我担心在程序中执行双星号(**
)之间的“重置”按钮时按下“重置”按钮。那时,没有计划执行的延迟命令,因此“重置”不会取消任何延迟命令。但是,在此之后,即使用户打算重置倒计时,也将安排一个新的延迟命令执行(设置afterID [after afterID [after afterID [after afterID [after Ind ...]
)。
I have implemented a countdown timer that has a "Reset" button for cancelling a countdown:
set LAUNCHTIME 5
set message $LAUNCHTIME
set afterId {}
proc countdown {remainingSeconds} {
global afterId message
# **
if {$remainingSeconds > 0} {
set message $remainingSeconds
# **
set afterId [after 1000 [list countdown [expr {$remainingSeconds - 1}]]]
} else {
set message "Takeoff!"
.start configure -state normal
}
}
label .message -textvariable message
button .start -text Start -command {
.start configure -state disabled
countdown $LAUNCHTIME
}
button .reset -text Reset -command {
# Reset timer, message, and button.
after cancel $afterId ;# <- XXX: Could this cause a race condition?
set message $LAUNCHTIME
.start configure -state normal
}
grid .message
grid .start
grid .reset
grid anchor . center
This is what it looks like when the "Start" button is pressed:
Is there a possible race condition when the "Reset" button is pressed while a countdown is occurring? I am worried about the possibility that the "Reset" button is pressed while the program is executing the parts between the double asterisks (**
) in the code above. At that point, there is no delayed command that is scheduled to execute, so the "Reset" does not cancel any delayed command. However, right after, a new delayed command will be scheduled to execute (set afterId [after 1000 ...]
), even though the user has intended to reset the countdown.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
TCL运行单线螺纹(至少在单个解释器中)。事件仅在事件循环中进行处理。这意味着您不必担心会发生一些可能会改变事物的事情,而执行代码的顺序块。
如果用户在
Countdown
Proc运行时单击重置按钮,则PROC一直持续到最后。当时,事件循环通过执行附加到按钮的命令选项的代码来恢复并处理按钮键。取消事件后,因此Countdown
将不会再次调用。同样,如果在事件之后的
在重置按钮运行的代码运行时到期,则代码完成,请在
事件开始后的的代码之前取消事件。
Tcl runs single threaded (at least within a single interpreter). Events are only handled in the event loop. That means that you don't have to worry that something happens that could change things while a sequential block of code is executed.
If the user clicks the Reset button while the
countdown
proc runs, the proc continues all the way to the end. At that point the event loop resumes and handles the button-click by executing the code attached to the -command option of the button. That cancels the after event, socountdown
will not be called again.Similarly, if the
after
event expires while the code attached to the Reset button runs, the code completes, canceling the after event before the code of theafter
event starts.