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 |