On Thu, 13 Oct 2005, Shea Martin wrote:

> I have a TK app.  On a button presses, I call a windows copy command which 
> can take up to 10 minutes to run. In order to not freeze the GUI, so that the 
> gui can be doing other stuff, I launch the command in a thread.
>
> Running the command with system, does not let me get the output of the 
> command, thought it does not lock gui up at all.  So, I tried two other 
> versions.  I had the most success with version 3. I believe version 3 is what 
> the TkTextIo example uses in ruby 1.8.3. See below.
>
> # callback for tk button press
> def buttonPress
>  Thread.new do
>    Button.state( "disable" );
>    runCommand( "copy /Y bigfile1 dest1" );
>    runCommand( "copy /Y bigfile2 dest2" );
>    runCommand( "copy /Y bigfile3 dest3" );
>    Button.state( "active" );
>  end
> end
>
> #version 1
> def runCommand( cmd )
>  system( cmd )
> end
>
> #version 2
> def runCommand( cmd )
>  IO.popen( cmd ) do | cmd_out |
>    cmd_out.each_line do | line |
>      MyTextArea.insert( 'end', line, 'normal' )
>    end
>  end
> end
>
> #version 3
> def runCommand( cmd )
>  cmd_pipe = IO.popen( cmd )
>  t = Thread.new { cmd_pipe.each{ | line | addText( line ) } }
>  t.join
> end
>
> Only version 1 allows teh gui to remain responsive.  Unfortunately it does 
> not capture the output of the copy command.  I would like to something with a 
> fork, though win32 ruby does not seem to support it.
>
> Any ideas.
>
> Thanks,

i just found this lying around - i thought i'd messed with it before - it runs
unmodified and without blocking on *nix and win*:

   require "tk"

   thread_runner = lambda do
     Thread::new do
       pipe = IO::popen "ruby", "rb+"
       pipe.write <<-program
         STDERR.reopen STDOUT
         STDOUT.sync = true
         loop{ p [Process::pid, Time::now]; sleep 0.42 }
       program
       pipe.close_write
       pipe.each{|line| puts line}
     end
   end

   TkButton::new(nil,
     "text" => "start thread/process",
     "command" => thread_runner).pack( "fill" =>"x")

   TkButton::new(nil,
     "text" => "say hello",
     "command" => lambda{puts "HELLO"}).pack( "fill" =>"x")


   TkButton::new(nil,
     "text" => 'quit',
     "command" => lambda{exit}).pack("fill" => "x")

   Tk::mainloop

with it you can start multiple threads reading pipes connected to multiple
processes while the gui still responds.

hth.

-a
-- 
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze.  --Nagarjuna
===============================================================================