0

我需要能够设置变量以从线程内部结束 vwait。这是因为我有一个循环,它通常会锁定交互器,因此它运行的任何 GUI 都会锁定,直到它完成。

我希望它像这样的睡眠命令一样运行:

global EndSleep
after ${SleepTime_ms} set EndSleep 1
vwait EndSleep

只有当查询设备的 while 循环退出时,我才需要设置 vwait 变量。

这是我目前的代码:

    proc ::VISA::Wait {VisaAlias} {
    # Link global variable
    global EndWait

    # Execute commands in a thread so the GUI is not locked while executing
    set Thread [thread::create]
    thread::send ${Thread} [list set VisaAlias ${VisaAlias}]
    thread::send ${Thread} {
        source MolexVisa.tcl

        # Temporarily make new connection with device
        VISA::Connect ${VisaAlias}

        # Query operation complete bit
        VISA::Query ${VisaAlias} "*OPC?"

        # Continue to attempt to read OPC bit until any response is given; typically 1
        while {[string equal [VISA::Read ${VisaAlias}] ""]} {}

        # Destroy temporary connection
        VISA::Disconnect ${VisaAlias}

        # Set vwait variable
        set EndWait 1
    }

    # Wait for thread to end
    vwait EndWait

    # Mark thread for termination
    thread::release ${Thread}
}

目前该线程仍在冻结 GUI。此外,由于线程中的变量和我期望的变量不同,显然它只是永远等待。

任何建议或帮助表示赞赏。我相信我已经用尽了所有其他更实用的方法来完成这项任务,但欢迎提供更多见解。

4

1 回答 1

2

使用-async标志thread::send。默认情况下,::thread::send在脚本执行之前一直阻塞(这在大多数情况下会破坏线程的使用)。

如果你使用-async标志,你也可以使用可选的变量参数thread::sendvwait例如

set tid [thread::create {
    proc fib n {
        if {$n == 0 || $n == 1} {return 1}
        return [expr {[fib [expr {$n - 1}]] + [fib [expr {$n - 2}]]}]
    }
    thread::wait
}]
::thread::send -async $tid [list fib $num] result
vwait result
::thread::release $tid
# ... do something with result

这应该可以防止 GUI 冻结。请注意,斐波那契的这种实现并不是最好的,它是“一些昂贵的计算”的占位符。

于 2013-02-12T06:50:22.270 回答