Hello. I’m writing a ruby/gtk2 application scheduling application
for my university, which does some work in a separate thread,
to keep the UI usable. That separate thread might fail, in which
case I’d like to show an error dialog back in the UI. Now, I’ve
tried this without exceptions first (though I’d rather have it use
exceptions), like this:
def do_scheduling # called by the event
Thread.new do
success = long_complicated_task
unless success
error_dialog “Scheduling unsuccessful”
else
…
end
end
end
Now, I’ve had this dialog fail on me, but I can’t reproduce it
(threads will be threads…). Something about another thread already
being in the mainloop. How can I secure myself against this?
Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Hello. I’m writing a ruby/gtk2 application scheduling application
for my university, which does some work in a separate thread,
to keep the UI usable. That separate thread might fail, in which
case I’d like to show an error dialog back in the UI. Now, I’ve
tried this without exceptions first (though I’d rather have it use
exceptions), like this:
I think someone should write a FAQ.
AFAIK you simply cannot create two mainloops, so you can’t fire a dialog
from a different ruby thread. You can instead set some sahred variable
and
fire the dialog from the main thread.
AFAIU this is a GTK limitation (the GTK main loop can’t contain another
one
in the same thread, and ruby threads are not real system threads).
–
Mirko M.
Ubuntu: an African word meaning “I can’t figure out how to configure
Debian”
Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
On Wed, Oct 18, 2006 at 02:28:28PM +0200, Ohad L. wrote:
Now, I’ve had this dialog fail on me, but I can’t reproduce it
(threads will be threads…). Something about another thread already
being in the mainloop. How can I secure myself against this?
What worked fine for me so far is just doing it in an idle handler.
I don’t know if this is really thread-safe, and I gather that idle
handlers
are almost always a bad thing, but anyway, it would look something like
this:
def error_dialog(msg)
Gtk.idle_add do
dialog = Gtk::MessageDialog.new nil,
Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
Gtk::MessageDialog::ERROR, Gtk::MessageDialog::BUTTONS_OK, msg
dialog.run
dialog.destroy
false
end
end
That false on the last line is important, or else it will loop.
hth,
Markus
Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
AFAIK you simply cannot create two mainloops, so you can’t fire a dialog
from a different ruby thread. You can instead set some sahred variable and
fire the dialog from the main thread.
For the record and to possibly help other readers:
I wholeheartedly agree with Mirko. I’ve had some aborts in my
application “booh” because of this problem. I’ve tried to solve the
problem (with the help of Mirko) down to the application level (at the
Gtk level actually), but my message was never replied:
Hence, I’ve workarounded the problem in my program by using a data
structure to send Gtk method calls to the main Thread. The following
explains it:
on startup, from the main thread, create a mutex and a timeout loop
which will perform the Gtk method calls:
$protect_gtk_pending_calls = Mutex.new
$gtk_pending_calls = []
Gtk.timeout_add(100) {
$protect_gtk_pending_calls.synchronize {
for closure in $gtk_pending_calls
closure.call
end
$gtk_pending_calls = []
}
true
}
add a method called whenever some Gtk method calls are desired:
def gtk_thread_protect(&proc)
if Thread.current == Thread.main
proc.call
else
$protect_gtk_pending_calls.synchronize {
$gtk_pending_calls << proc
}
end
end
For example, when refreshing a progress bar value doing a heavy
computation from within a separate ruby thread:
gtk_thread_protect { pb.fraction = value }
add a method to flush pending Gtk method calls, to be used when
some Gtk objects are about to be destroyed on which pending Gtk method
calls may be undone yet
def gtk_thread_flush #- try to lock. we cannot synchronize blindly because this might
be called from #- within the timeout flushing procs. if this is the case, not
doing anything #- should be ok since the timeout is already flushing them all.
if $protect_gtk_pending_calls.try_lock
for closure in $gtk_pending_calls
closure.call
end
$gtk_pending_calls = []
$protect_gtk_pending_calls.unlock
end
end
Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
I’ve found that this works too, without using the idle loop - instead
of using ‘run’, using ‘show’ and connection the ‘response’ signal to
dialog.destroy.
Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.