To start I will say I have read through the read "Problem with threads" to try and work around this problem, but I do not think I understand what is happening enough to make use of the info I found there. My app is pretty basic and does some text processing on 2 files and uses WIN32OLE to take the data and put it an excel sheet. The processing is really fast, but loading up Excel and doing output via WIN32OLE is taking a little bit. I''m fine with the speed, but while its doing the processing and output the entire GUI freezes and looks like crap for about 5 seconds. Basically I''m looking for an easy way to avoid this so the end user doesnt freak out and think the program crashed or anything. I found this code in the thread mentioned above: def on_init t = Wx::Timer.new(self, 55) evt_timer(55) { Thread.pass } t.start(100) which would be used in the on_init of the main App. I understand what it is doing (creates a 100ms timer which calls Thread.pass every iteration), but I don''t understand how this can help the problem. I assume that if I do my processing in a new thread, this timer just keeps passing the the execution around between Wx and my thread until it finishes, which would hide the unresponsiveness of the GUI. However, I must be wrong since this doesn''t work, or I''m doing it wrong. I have a button called ''run'' which calls the following method: --------------- button code ------------------------------- def run dialog = Wx::FileDialog.new(self, "Save Report", "", "APReport.xls", "Excel Files (.xls)|*.xls", Wx::SAVE|Wx::OVERWRITE_PROMPT) file1 = @file1.get_value.to_s.strip file2 = @file2.get_value.to_s.strip if file1 == '''' or file2 == '''' info = sprintf("Please make sure you have selected both files.") dialog2 = Wx::MessageDialog.new(self, info, "Missing File?") dialog2.show_modal() elsif dialog.show_modal() == Wx::ID_OK save_path = dialog.get_path() puts save_path puts file1 puts file2 $t = Thread.new { ap = APBook.new ap.run(file1, file2, save_path) ### THIS IS THE PART THAT TAKES } ### SOME TIME end end And my on_init looks like this: ------------- on_init -------------------- class MyApp < Wx::App def on_init t = Wx::Timer.new(self, 55) evt_timer(55) { $t.pass if !$t.nil? && $t.methods.include?("pass") } t.start(100) SimpleFrame.new(nil, :size => Wx::Size.new(400, 180), :title => "AP Report").show end end This is basically cobbled together from the code Raine posted in ''Problem with threads'' which she stated did not work... but it seems that no one ever got to the crux of the issue of why it didnt work. So I ask, in exasperation, what am I doing wrong? Where do I go from here? Thanks for reading, this got a bit longer than I intended... -Alex C
Alex Fenton
2007-Jun-28 19:03 UTC
[Wxruby-users] Keeping GUI responsive while processing data
Hi Alex Alex Ciarlillo wrote:> the entire GUI freezes and looks like crap for > about 5 seconds. Basically I''m looking for an easy way to avoid this so > the end user doesnt freak out and think the program crashed or anything. > > I found this code in the thread mentioned above: ><snip>> $t = Thread.new { > ap = APBook.new > ap.run(file1, file2, save_path) ### THIS IS THE PART THAT TAKES > } ### SOME TIME >This looks fine - for testing I tried an example replacing your win32OLE code with a simple Thread.new { sleep 5; puts ''done'' } I don''t think you need to save the thread as a global ...> ------------- on_init -------------------- > > class MyApp < Wx::App > def on_init > t = Wx::Timer.new(self, 55) > evt_timer(55) { $t.pass if !$t.nil? && $t.methods.include?("pass") }Here you should be calling the class method Thread.pass - there is no instance method Thread#pass in ruby, so execution never switches to the OLE thread in your statement. There is an instance method Thread#run, but I find working with the code above that simply evt_timer(55) { Thread.pass } works fine and the GUI remains responsive. Does this help? cheers alex
Alex Ciarlillo
2007-Jun-28 19:34 UTC
[Wxruby-users] Keeping GUI responsive while processing data
Alex Fenton wrote:> Hi Alex > > Alex Ciarlillo wrote: > >> the entire GUI freezes and looks like crap for >> about 5 seconds. Basically I''m looking for an easy way to avoid this so >> the end user doesnt freak out and think the program crashed or anything. >> >> I found this code in the thread mentioned above: >> >> > <snip> > >> $t = Thread.new { >> ap = APBook.new >> ap.run(file1, file2, save_path) ### THIS IS THE PART THAT TAKES >> } ### SOME TIME >> >> > This looks fine - for testing I tried an example replacing your win32OLE > code with a simple > > Thread.new { sleep 5; puts ''done'' } > > I don''t think you need to save the thread as a global ... > > >> ------------- on_init -------------------- >> >> class MyApp < Wx::App >> def on_init >> t = Wx::Timer.new(self, 55) >> evt_timer(55) { $t.pass if !$t.nil? && $t.methods.include?("pass") } >> > Here you should be calling the class method Thread.pass - there is no > instance method Thread#pass in ruby, so execution never switches to the > OLE thread in your statement. > > There is an instance method Thread#run, but I find working with the code > above that simply evt_timer(55) { Thread.pass } works fine and the GUI > remains responsive. > > Does this help? > > cheers > alex > _______________________________________________ > wxruby-users mailing list > wxruby-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/wxruby-users >Worked like a charm :) I thought I tried using Thread.pass earlier and it didnt work, but I realized it was because I was trying to run a different file than the one I was editing (duh). It''s all working great now tho. Thanks!