Code Comments
Programming Forum and web based access to our favorite programming groups.On Apr 1, 9:09 pm, Andrew Mangogna <amango...@mindspring.com> wrote:
> The usual approach to this situation is to use event driven I/O. In genera
l
> terms it goes something like this:
>
> 1. Run the command at the end of a pipeline that you are going to read.
> The "open" command can do this for you when it is used in its
> open "| cmd ..." form.
>
> 2. Set the channel returned from "open" to be non-blocking using
> the "fconfigure" command (or "chan configure" for 8.5).
>
> 3. Set up an event handler to run when the channel becomes readable. This
is
> accomplished with the "fileevent" command (or "chan event" in 8.5).
>
> 4. In the event handler, the channel is read and the text can be inserted
> into a text widget using something like ".t insert end ...". The event
> handler does need to detect EOF and close the channel when that occurs.
>
> This way of doing the I/O allows the GUI event loop to continue to run whi
le
> waiting for the asynchronous output from the other process. When the outpu
t
> from the other process arrives, the channel becomes readable and the event
> handler is dispatched. This is very analogous to what happens when command
s
> are executed by pressing GUI buttons. It is just in this case you have
> arranged for the I/O to come from some place other than the mouse.
>
> The wiki is always a good source for specific code sequences of this sort.
> --
> Andrew Mangogna
Andrew,
Thank you very much. You input was very useful and I managed to get
the behavior I wanted!
Just for anyone who might be interested here is what I wrote:
proc wrtToText {txt out} {
$txt configure -state normal
$txt insert end $out
$txt see end
$txt configure -state disabled
}
proc wrtChanToText {chan} {
while {![eof $chan]} {
wrtToText .t "[gets $chan]\n"
update
}
}
text .t -height 10 -width 120
pack .t
set host 127.0.0.1
set cmd "tclsh download_bkup.tcl $host user pass"
set f1 [open "|$cmd" r]
fconfigure $f1 -buffering line
fileevent $f1 readable [wrtChanToText $f1]
Any comments appreciated.
Thanks,
Pavel.
Post Follow-up to this messagePavel Novozhilov wrote:
> On Apr 1, 9:09 pm, Andrew Mangogna <amango...@mindspring.com> wrote:
[snip some long winded diatribe]
>
> Andrew,
>
> Thank you very much. You input was very useful and I managed to get
> the behavior I wanted!
>
> Just for anyone who might be interested here is what I wrote:
>
> proc wrtToText {txt out} {
> $txt configure -state normal
> $txt insert end $out
> $txt see end
> $txt configure -state disabled
> }
>
> proc wrtChanToText {chan} {
> while {![eof $chan]} {
> wrtToText .t "[gets $chan]\n"
> update
> }
> }
>
> text .t -height 10 -width 120
> pack .t
>
> set host 127.0.0.1
> set cmd "tclsh download_bkup.tcl $host user pass"
>
> set f1 [open "|$cmd" r]
> fconfigure $f1 -buffering line
> fileevent $f1 readable [wrtChanToText $f1]
>
>
> Any comments appreciated.
>
> Thanks,
> Pavel.
I'm a bit concerned over the implementation of "wrtChanToText". By my
reading of the code, once the channel becomes readable, you remain in the
loop performing blocking I/O and fail to clean up the open channel when EOF
is reached. I would try something like (the following completely untested
code):
proc wrtChanToText {chan} {
if {[eof $chan]} {
close $chan
return
}
while {[gets $chan line] >= 0} {
wrtToText .t $line\n
}
}
Then is would be very important to put the channel in non-blocking mode
using:
fconfigure $f1 -blocking false
(FYI, "-buffering" only affects flushing the internal buffer on output for a
channel). With these changes, the GUI should continue to respond even if
the output of the process comes in spurts with big time breaks in between.
In your case the process may have produced all of its output at once and so
you didn't notice the GUI processing begin hung up. But, in general, it is
better to use event driven I/O on non-blocking channels. Also, cleaning up
the open channel becomes important if this is a long running application.
--
Andrew Mangogna
Post Follow-up to this message* Andrew Mangogna <amangogna@mindspring.com>
| I'm a bit concerned over the implementation of "wrtChanToText". By
| my reading of the code, once the channel becomes readable, you
| remain in the loop performing blocking I/O
The use of 'update' in the loop may trigger the 'fileevent readable'
and enter 'wrtChanToText' again, where the use of update may trigger
the ... [repeat as required] Put 'puts' statements when entering and
leaving 'wrtChanToText' to see if this is the case.
Instead of using 'update', just read all available input non-blocking
and let the regular event loop call the proc again via fileevent.
fconfigure $f1 -blocking false
# Note that "-buffering line" is useless for INPUT, it affects only OUTPUT
fileevent $f1 readable [wrtChanToText $f1]
proc wrtChanToText {chan} {
if {[eof $chan]} {
close $chan
return
}
set text [read $chan]
if {[string length $text] > 0} {
wrtToText .t $text
}
}
http://wiki.tcl.tk/880 has more on 'fileevent'.
R'
Post Follow-up to this message* Ralf Fassel <ralfixx@gmx.de> | fileevent $f1 readable [wrtChanToText $f1] Correction: fileevent $f1 readable [list wrtChanToText $f1] R'
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.