[pygtk] Waiting for a callback to run
Robert Schroll
rschroll at gmail.com
Mon Feb 21 11:09:53 WST 2011
On 02/20/2011 03:08 PM, Stephen Langer wrote:
> This is what we do:
>
> class IdleBlockCallback:
> def __init__(self, func, args=(), kwargs={}):
> self.func = func
> self.args = args
> self.kwargs = kwargs
> self.event = threading.Event()
> self.result = None
> def __call__(self):
> gtk.gdk.threads_enter()
> try:
> self.result = self.func(*self.args, **self.kwargs)
> finally:
> gtk.gdk.flush()
> gtk.gdk.threads_leave()
> self.event.set()
> return False # don't repeat
>
> def runBlock(func, args=(), kwargs={}):
> callbackobj = OOFIdleBlockCallback(func, args, kwargs)
> callbackobj.event.clear()
> gobject.idle_add(callbackobj, priority=gobject.PRIORITY_LOW)
> callbackobj.event.wait()
> return callbackobj.result
>
Thank you, thank you, thank you - this is exactly what I was looking
for. For some reason, I didn't think to look in Python's threading
module. Two questions:
1) Since all GTK stuff is happening in the mainloop thread, I'm only
calling gobject.threads_init(), not gtk.gdk.threads_init() (as suggested
here: http://library.gnome.org/devel/gtk-faq/stable/x499.html) Am I
correct in understanding that I don't need to call
gtk.gdk.threads_enter() and _leave() in the callback? (I've taken them
out, and nothing seemed to break.) What about the flush()?
2) I'd like to use this code in a project to be released under the BSD
license. Is that okay with you?
> Call runBlock on the worker thread. Be sure that you're really on the worker thread, because if you call it on the main thread it will hang.
If I understand things correctly (unlikely), gobject.main_depth() will
be greater than zero in the main loop thread and zero in the worker
threads. (At least if I only start the main loop in one thread.) So
I've written this function to ensure code is called in the main loop.
Limited testing suggests it's working.
def run_in_main_loop(func, *args, **kwargs):
if gobject.main_depth():
# In the main loop already
return func(*args, **kwargs)
callbackobj = IdleBlockCallback(func, args, kwargs)
callbackobj.event.clear()
gobject.idle_add(callbackobj, priority=gobject.PRIORITY_LOW)
callbackobj.event.wait()
return callbackobj.result
Thanks again,
Robert
More information about the pygtk
mailing list