有时,我们需要等待某个操作的完成。这里的操作可以用一个Tcl命令来代替。使用 trace 和 vwait 可以完成这个事情。
#------------------------------------------- # Usage: # use trace to wait some command to finish #------------------------------------------- namespace eval ::noyesno::testing { proc _traceProc { args } { set name [lindex $args 0 0] set op [lindex $args end] set waitVar [namespace current]::[regsub -all {::} $name "__"] set time [clock format [clock seconds] -format "%H:%M:%S"] switch $op { "enter" { puts "DEBUG: $time $args" } "leave" { incr $waitVar puts "DEBUG: $time $args" } } } proc waitmgr { op name {val 0}} { set waitVar [namespace current]::[regsub -all {::} $name "__"] switch $op { "init" { set $waitVar 0 puts "DEBUG: install wait for $name" trace add execution $name leave [namespace current]::_traceProc trace add execution $name enter [namespace current]::_traceProc } "remove" { trace remove execution $name leave [namespace current]::_traceProc trace remove execution $name enter [namespace current]::_traceProc unset $waitVar } "set" { set $waitVar $val } } } proc wait { name {sec {4000}} {expect ""}} { set waitVar [namespace current]::[regsub -all {::} $name "__"] if {$expect != "" && [set $waitVar] == $expect} { puts "DEBUG: already finished" return } puts "DEBUG: trace start: $name = [set $waitVar]" after $sec set $waitVar -1 vwait $waitVar after cancel set $waitVar -1 if { [set $waitVar] < 0 } { puts "INFO: **TIMEOUT** wait $name = [set $waitVar]" } else { puts "INFO: **OK** wait $name = [set $waitVar]" } return $waitVar } } # Usage Demo proc proc_hello {args} {puts "inside proc_hello"} after 2000 proc_hello after 4000 proc_hello ::noyesno::testing::waitmgr init proc_hello ::noyesno::testing::wait proc_hello 3000 ::noyesno::testing::wait proc_hello 3000 2 after 5000 proc_hello ::noyesno::testing::wait proc_hello 3000