From: "Ara.T.Howard" Date: 2004-02-26T09:04:47+09:00 Subject: thread gurus please help... following is a _simulation_ of a rather complex gui i'm working on. the gui run a procedure which, itself, is communication with many other processes via Open3::popen3 (i _need_ the stderr)... anyhow, i'm having fits getting the gui to update and do all the io (select/read, etc). this code seems to work fine but i am very conerned that something might bite me later... if anyone would care to comment on the interactions between the io and threads and if this is a reccomended approach i'd love to hear it... remember this code might look a bit funny but it demonstrative of what my code actually does. thanks in advance for any help/advice ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== require 'tk' require 'open3' require 'io/wait' require 'io/nonblock' require 'thread' $VERBOSE=nil STDOUT.sync = STDERR.sync = true Thread.abort_on_exception = true threads = [] #setup gui root = TkRoot.new label_a=TkLabel.new root, :text=>'label_a' label_b=TkLabel.new root, :text=>'label_b' label_a.pack label_b.pack # start the gui running threads << Thread.new{ Tk.mainloop } # simulation of my processing loop - which is communcating with another # process and updating a widget with it's output def update label, program command="ruby -e '#{ program }'" i,o,e = Open3::popen3 command i.close # we run in a thread so entire process is not blocked on io # we DO need to wait for it to complete though, because in the real code i # depend on values which are returned... Thread.new do o_done = false e_done = false loop do rios, = select [o, e], nil, nil rios.map do |rio| break if o_done and e_done if rio.eof? rio == o ? o_done = true : e_done = true next end # i like this better, but it hangs # putting a critical section results in deadlock # a semaphore is too slow... #rio.nonblock{ text = rio.read } # less elegant but works... text = '' sleep(0.42) and Thread.pass until rio.ready? text << rio.getc while rio.ready? label.configure :text=>text end end end.join end # start background processing which will update the labels threads << Thread.new{ update label_a, '4.times{p Time.now; sleep 1}' } threads << Thread.new{ update label_b, '4.times{|i| p "foobar_#{ i }"; sleep 1}' } # wait for everyone to finish #threads.map{|t| t.join} sleep ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== -a -- =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328 | URL :: http://www.ngdc.noaa.gov/stp/ | TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done ===============================================================================