The standard way to do this to to use tcl's event loop by setting the I/O channel to non-blocking and using fileevent
or chan event
; however, the tclvisa documentation states that fileevent is not supported on visa channels.
So the next best thing is to use non-blocking I/O (which just sets the timeout to 0) and either busyloop reading the channel or reading it after a delay; either of these should be handled with the event loop rather than by sprinkling update
around (which has undesirable side effects).
So to busyloop you could do something like this:
proc busyread {v n} {
if {$::readdone == 1} {set ::$n "Error"}
set r [visa::read $v]
if {$r == ""} {
after 5 [list busyread $v $n]
} else {
set ::$n $r
set ::readdone 1
}
}
set f [visa::open ...]
fconfigure $f -blocking 0
after 1000 [list set ::readdone 1]
set ::readdone 0
busyread $f result
vwait ::readdone
# $result will now be either the result, or "Error"
This continuously reschedules the read
as long as it keeps coming back empty.
This will need to be restructured a bit to work within a larger gui program (the vwait and timeouts would need to be done differently), but this shows the basic method.