[fxruby-users] Updating GUI while doing slow IO-operations
fxrbu1 at gi2.herzkes.de
fxrbu1 at gi2.herzkes.de
Fri Sep 21 02:59:44 EDT 2007
Kenneth Juul wrote:
> I am noob struggling with a problem and hope some of you guys can
> help. I believe it is a matter of concept, not code errors, so I am
> not posting the code:
> I have made a rather large program in Ruby for use in Windows. The
> user interface is made with fxruby, of course. The program is
> "talking" to a small embedded computer over both serial and ethernet
> interfaces. Some of this communication is taking a while, several
> minutes actually, and this is when my problem occurs:
> During slow, time consuming operations, the GUI freezes / hangs.
> Sometimes it just turn "windows-white" and stays like this until the
> IO is done, other times it just freezes the last window until IO is
> I have done some vague attempts on starting of the IO withing separate
> threads without any improvement. I also have tried some calls to
> flush(), forceRefresh(), refresh(), update() and so on, without any
> Enlighten me please!
It has been a while since I have looked at ruby's sources, but I think
the explanation goes like this:
The ruby interpreter itself is single-threaded. The threads that you see
in ruby are provided by the ruby interpreter, not the operating system.
Whenever I/O occurs, or at other times when threads are switched, the
ruby interpreter tries to select a thread that will most likely not
block. For this purpose, it uses the unix-ish "select" system call. Even
on windows systems.
Windows provides a "select" API function, but, it only works with
network sockets. And even there, it works differently for checking
writeability than on Unix.
So for IO objects on windows that are not network sockets, the ruby
interpreter assumes that any IO operation on them will not block. If
this assumption is false, then the whole ruby interpreter will be
blocked until the IO operation completes. Therefore, no GUI updates.
Your way out of this dilemma: Not easy. You need to decouple the Gui
from the Communication layer. 2 Options:
1) Separate processes for GUI and IO. Then you can either use TCP
sockets (and "select") or disk files (periodical polling) for
communication between them.
2) Do your IO in C/C++: use a Ruby extension that starts a dedicated
thread for the communication with your device. This new thread must
never call any function of the ruby interpreter. Instead, your ruby
program has to call some checking function in your extension
periodically to check if the IO operation has completed yet.
More information about the fxruby-users