|
From: Jonathan P. <jp...@dc...> - 2005-04-12 09:39:59
|
Hi,
I've been trying to do some Ruby processing in the background (parsing
a large XML file with REXML upon opening a document) while letting the
Cocoa GUI still be responsive.
I've tried a number of techniques to achieve this, and was wondering if
anybody had any comments or suggestions - particularly to do with how
Ruby threads are expected to work in RubyCocoa.
I have a document window, and during loading I'm posting a sheet with
an indeterminate progress bar in it. I want the progress bar to animate
(and other windows/menus to be responsive) while doing the REXML
parsing.
(1) I've tried calling the run loop in a loop from a Ruby thread to get
events processed whilst REXML works on the main Ruby thread. For some
reason I haven't figured out, no events were processed. This may be
because I was calling the run loop from within an existing run loop
invocation.
(2) I've tried doing the REXML processing in a Ruby thread and calling
NSApplication endSheet.
Both of these techniques suffered from the problem of invoking Cocoa
methods from a non-main Ruby thread. Largely things would be okay, but
occasionally AppKit would get unhappy because the per-NSThread
exception handler list (NS_DURING etc) becomes invalid when Ruby
switches the C stack between its threads.
This is unfortunate, because it means we can't even call normally
thread-safe Foundation methods because Cocoa exception handlers are
used in RubyCocoa.
Any ideas how to get around this?
Thanks.
Jonathan
Below are some code fragments describing (1) and (2).
(1)
OSX::NSApplication.sharedApplication.beginSheet_...(@sheet,...)
done = false
rl = OSX::NSApplication.sharedApplication.currentRunLoop
t = Thread.new do
rl.runMode_beforeDate(OSX::NSDefaultRunLoopMode, OSX::NSDate.date)
until done
end
@doc = REXML::Document.new(big_xml_string)
## code here to populate GUI from contents of @doc
done = true
t.join
OSX::NSApplication.sharedApplication.endSheet(@sheet)
(2)
OSX::NSApplication.sharedApplication.beginSheet_...(@sheet,...)
Thread.new do
@doc = REXML::Document.new(big_xml_string)
## code here to populate GUI from contents of @doc
OSX::NSApplication.sharedApplication.endSheet(@sheet)
end
|