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!