WxRuby refresh from a long running function

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

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.

-----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-----

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 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 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