Hi All, This is my first post and I am a complete (well almost complete) noob at WxRuby. I have programmed in Ruby for a while, but now I am trying my hand at a GUI base program running on Windows. There is quite a bit of serial communication between the app and a external device. The problem I am facing is a function call that takes a long time to complete before returning to WxRuby. My application is pretty simple with a start button, a few fields that display data and a progress bar. There are a couple of dialogs that pop up during the call as well. Advancing the progress bar and displaying dialogs works just fine, except the dialog windows do mess up the top application appearance once the dialog is dismissed. Of course once the function call is complete the screen will refresh as expected. I have tried setting a separate thread for the function and using a timer with Thread.pass as shown in the WxRuby thread example. Although the GUI is nice an responsive, the performance of the long running function is unacceptable. So is there a callback that can be done to allow the ruby app to run that I can make from this long running function or some other way to use a separate thread more efficiently. Ruby 1.8.7, WxRuby 2.0.1 Any help is appreciated. Mark
on 2011-10-06 21:36
on 2011-10-11 06:50
Hi Mark! The answer in my experience is that you'll have to spawn another ruby process and do the processing normally done in the long-running function there. Basically, you need to use inter-process communication to do your asynchronous processing instead of threads. Unfortunately, this is unpleasant to do on Windows because of Ruby's poor support for spawning processes compared to Linux, but it can be done and it'll give you a superior result to any solution involving Ruby threads. I see you're using Ruby 1.8.7. Just a heads-up that you'll find Ruby 1.9 won't give you a better result; I've tried that thinking it would work because of 1.9's operating-system thread implementation, but it doesn't improve things because Ruby still has a Global Interpreter Lock that prevents more than one thread doing anything at one time. I would put your effort straight into an IPC solution. I think you'd find that the performance of the method you've tried would be fine on OSX or Linux under GTK+, I have found that. It's probably because of differences in their GUI implementations compared to Windows. If that's an option for you, that might save you some time. I do remember FXRuby doing much better at this than wxruby. FXRuby always worked perfectly fine in this situation, I'd like to look into improving this for wxruby one day.
on 2011-10-11 10:43
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Am 11.10.2011 04:38, schrieb David B.: > I see you're using Ruby 1.8.7. Just a heads-up that you'll find > Ruby 1.9 won't give you a better result; I've tried that thinking > it would work because of 1.9's operating-system thread > implementation, but it doesn't improve things because Ruby still > has a Global Interpreter Lock that prevents more than one thread > doing anything at one time. Things are getting better, although you're right and the GIL (or GVL, "Global VM Lock") is still there. Doing I/O for example releases the GIL to allow other threads to run while the I/O thing is processed. Read about the Ruby API's rb_thread_blocking_region() if you want to know how to achieve this in C extensions. The Pickaxe for 1.9 covers this in chapter 29 "Extending Ruby" starting on page 833 with "The Threading Model". > I do remember FXRuby doing much better at this than wxruby. FXRuby > always worked perfectly fine in this situation, I'd like to look > into improving this for wxruby one day. FYI: FxRuby isn't worked on anymore, so although it may still work at the moment, that isn't guaranteed to stay like this. Valete, Marvin -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJOk+PqAAoJELh1XLHFkqha+DQIAJzCyHDMxSuakNP+Z72P+lsD ZjjhRWSYzzNrnjcldfvk3VzNMJRvWVh87UGWojfaoRcF6smjkjSxSJXWl0PRObQi k5pscB5axYmLnKPRqF4DNLthoIdZ/IvDvUPe5gCrDEasilcUZSpr5eHapz4RIKeT HzIQDhgxj0L/XBIic9OMeG4yRRBxPKP8CyRxk5C+eOrb2f0Vfu3UPTWeJdoVXFba cvyvDCcwHBajzm20e1zg9xsjmKhv7QsK2mC9Kgr1QImp24UAH8BJb8cJVPrWaYC5 BgneNdyI2V5Aa/Q59MKo5KNGsiPXRFqWEmSrQPt3+ncKURV0LfSuetodX3X8Xsw= =c880 -----END PGP SIGNATURE-----
on 2011-10-11 11:11
Thanks for the tip on rb_thread_blocking_region Marvin, I'll look at that sometime. Does the wxruby team have a view as to how likely that approach would be to work, has anyone looked at it? And you're right about FXRuby, I wouldn't recommend that people use it. I just mentioned it more to say that I've seen threads working ok in other Ruby GUI toolkits. Despite this thread issue, wxruby is still a far better choice.
on 2011-10-11 12:42
On 11/10/11 07:50, David B. wrote: > Thanks for the tip on rb_thread_blocking_region Marvin, I'll look at > that sometime. Does the wxruby team have a view as to how likely that > approach would be to work, has anyone looked at it? I have looked at it, briefly. I'm not sure how well it would work for the GUI situation, where the UI has to remain responsive while an arbitrarily long (possibly IO-bound) process completes. The wxWidgets threading solution (for more complex tasks, where evt_idle / safe_yield etc are insufficient) is that the main Wx (event loop) thread keeps running, and the worker thread notifies it of progress by posting Wx::Events to it. However, in wxRuby, processing events requires the ruby interpreter to be running, and it seems that rb_thread_blocking_region doesn't allow re-entry to the interpreter. However, I haven't experimented with this in latest versions of Ruby 1.9 alex
on 2011-10-11 15:44
On 10/10/11 10:38 PM, David B. wrote: > any solution involving Ruby threads. > Thanks David, I will keep this in mind. In my case the solution is to rewrite some of the code as a state machine so as to allow the WxRuby loop to occasionally run. This should be fine as I am not really IO bound as much as there are some intentional processing delays that are required. Mark