Pregunta

I need to be able to set the variable to end a vwait from inside a thread. This is because I have a loop that normally locks the interperator and therefore any GUI it is running until it completes.

I'm wanting it to function just like a sleep command like this:

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

Only I need to set the vwait variable when a while loop that is querying a device exits.

Here is my code currently:

    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}
}

Currently the thread is still freezing the GUI. Also, since the variable in the thread and the variable I'm expecting aren't the same, obviously it just waits forever.

Any advice or help is appreciated. I believe I've exhausted all other more practical ways of accomplishing the task, but some more insight is welcomed.

¿Fue útil?

Solución

use the -async flag for thread::send. By default, ::thread::send blocks until the script has been executed (which defeats most of the time the use of threads).

If you use the -async flag, you can also use the optional variable argument to thread::send and vwait for that, e.g.

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

This should prevent the GUI from freezing. Note that this implementation of the fibonacci is not the best and is a placeholder for "some expensive calculation".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top