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
_______________________________________________
pygtk mailing list   [email protected]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/

Reply via email to