Tcl 如何在同一进程中中断vwait并启动另一个vwait

Tcl 如何在同一进程中中断vwait并启动另一个vwait,tcl,Tcl,为了演示我的问题,我编写了如下示例代码 button .a -text check -command abc pack .a set a 0 proc abc {} { pqr } proc pqr {} { global a puts "in pqr proc" # Want to break initial vwait set a 1 # Want to start a new vwait vwait a puts "

为了演示我的问题,我编写了如下示例代码

button .a -text check -command abc 
pack .a 
set a 0 
proc abc {} {
    pqr
}

proc pqr {} {
    global a
    puts "in pqr proc"
    # Want to break initial vwait
    set a 1
    # Want to start  a new vwait
    vwait a
    puts "vwait in pqr break"
}

vwait a
puts "Initial vwait break"
这样看来,我最初的梦想从未破灭

你知道如何做到这一点吗。
我想打破最初的vwait,并在同一个进程中启动一个新的vwait。

代码可以工作,但并不像您所期望的那样。特别是,在与按下按钮相关的事件处理完成之前,顶级
vwait a
不会继续,这发生在内部
vwait a
终止之后。(但是外部的
vwait
被标记为终止;它只想首先清除其内部调用堆栈。)这既简单,又很难解决,而且它也适用于
update
命令。Tcl社区有时会说
update
(是的,这也适用于
vwait
),这并非毫无意义

您真正想要做的是构造代码,以便它使用回调,并且最多只能使用一个
vwait

proc oneShotTrace {varname callbackScript} {
    upvar \#0 $varname v
    trace add variable v write [list oneShotTraceCallback $varname $callbackScript]
}
proc oneShotTraceCallback {varname callbackScript} {
    upvar \#0 $varname v
    trace remove variable v write [list oneShotTraceCallback $varname $callbackScript]
    uplevel \#0 $callbackScript
}

button .a -text check -command abc 
pack .a 
set a 0 
proc abc {} {
    pqr
}

proc pqr {} {
    global a
    puts "in pqr proc"
    # Want to break initial vwait
    set a 1
    oneShotTrace a {
        puts "vwait in pqr break"
    }
}

oneShotTrace a {
    puts "Initial vwait break"
}
vwait forever
这是对代码的实质性重新安排。通过使用TCL8.6的协同程序,您可以使事情不那么混乱

proc oneShotTrace {varname callbackScript} {
    upvar \#0 $varname v
    trace add variable v write [list oneShotTraceCallback $varname $callbackScript]
}
proc oneShotTraceCallback {varname callbackScript} {
    upvar \#0 $varname v
    trace remove variable v write [list oneShotTraceCallback $varname $callbackScript]
    uplevel \#0 $callbackScript
}

button .a -text check -command abc 
pack .a 
set a 0 
proc abc {} {
    coroutine c[incr ::co_count] pqr
}

proc pqr {} {
    global a
    puts "in pqr proc"
    # Want to break initial vwait
    set a 1
    oneShotTrace a [info coroutine]
    yield
    puts "vwait in pqr break"
}

oneShotTrace a {
    puts "Initial vwait break"
}
vwait forever

嗯,这似乎还是让人困惑。在真正的代码中情况就不那么糟糕了,在这种情况下,保持一个协同程序的复杂性比让局部堆栈框架中的变量保持不变的简单性和一个可理解的流程更为合理。(此外,您还可以将
收益率
隐藏在一个称为协同程序内部的过程中…

谢谢Donal。在多次点击按钮检查后,我在代码中面临的实际问题堆栈中有多个proc pqr条目。一段时间后,它会显示错误,比如太多嵌套求值(无限循环?)@SaurabhS是的,这就是问题的症结所在。不要在回调中调用
vwait