I just knocked up something to demonstrate the technique, I didn't do any debugging. For your purposes you need to handle multiple queues simultaneously, so you would need to use dequeue_nb() (non-blocking) in the while loop. You also need to coordinate the queues with their associated windows, so the logic required is slightly more complex.
This version, equally minimally tested, will run multiple concurrent commands as shown at the __END__. I've used Win32::Sleep to allow the updates to happen quickly whilst not running away with the cpu. You could use select, or Time::HiRes or yield() (though the latter tends to thrash the cpu!).
#! perl -slw use strict; use threads; use Thread::Queue; use IO::Pipe; sub runNGather { my( $Q, $cmd ) = @_; my $pipe = IO::Pipe->new(); $pipe->reader( "$cmd 2>&1" ); $Q->enqueue( $_ ) while <$pipe>; $Q->enqueue( '!!!EOF!!!' ); return; } my @Qs; for( @ARGV ) { push @Qs, [ new Thread::Queue ]; threads->create( \&runNGather, $Qs[-1][0], $_ )->detach; } require Tk; require Tk::ROText; my $mw = MainWindow->new; for my $Q ( @Qs ) { my $top = $mw->Toplevel(); my $label = $top -> Label( -text=>"STDOUT from script", -relief=>"groove" )->pack(); my $ro = $top->Scrolled( 'ROText', -width => 60, -height=>20, -scrollbars=>"e" )->pack(); # add close button my $close = $top->Button( -text => "Close window", -command => sub{ destroy $top; } )->pack(); push @{ $Q }, $ro; } # continuously display output while( 1 ) { last unless @Qs; for my $n ( 0 .. $#Qs ) { my $text = $Qs[ $n ][0]->dequeue_nb; next unless defined $text; if( $text =~ m[^!!!EOF!!!$] ) { my $Q = splice( @Qs, $n, 1 ); undef $Q->[0]; last; } my $ro = $Qs[ $n ][1]; $ro->insert("end", "$text"); $ro->update(); } $mw->update; Win32::Sleep .1; } $mw->MainLoop; __END__ P:\test>522177 "ping www.perlmonks.org" "ping www.bbc.co.uk" "dir /s \ +*.pl"
In reply to Re^3: Tk + threads
by BrowserUk
in thread Tk + threads
by knirirr
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |