12
Mar
07

Threading and (py)Gtk

At the request of a few people I have made a demo to share, showing how I do threading in a pygtk application (Conduit). I find the following approach seems to work reliably and requires little code. Other approaches can be found here and here.

This approach takes advantage of the fact that signal emission in glib has been threadsafe since glib 2.8 (IIRC). All communication with the GUI is done via gobject signals. There is definitely a compromise in the level of GUI fiddling that you can do, particularly when compared with the threads_enter/leave approach. However, I have found this signal based approach sufficent in my case, and that it encourages me to decouple the slow blocking tasks from the GUI.

A lot of the tasks in conduit take a long time (network limited), and there is no real need for extensive GUI interaction with them once they have been started. I am really only interested in their progress, and when they complete. With this in mind I have implemented the following approach;

  • FooThreadManager
    This class is the entry point for starting threads (the make_thread() method) . Its basically just a threadpool that starts threads with the appropriate arguments, while restricting the number of concurrent running threads below a user defined limit. It also connects the threads to the supplied user callbacks.
  • _IdleObject
    Like a normal gobject.GObject but emits all signals in the main thread
  • _FooThread
    A simple class which derives from both threading.Thread and _IdleObject. All work is done in run() and a signals are emitted when the thread completes and to show progress
  • Demo
    A simple demo (see screenshot) which can start a whole bunch of threads and receive notification when they complete.

FooThread Test Program

Anyway, the Example Code is a bit contrived and will certainly need some customization by the user but nonetheless may still be useful to others.

Update: Thanks to comments I fixed up a thread-safety issue. I had misunderstood that signal handlers get run immediately in emit(). Now the code emit()s on an idle_handler so all signals and callbacks are run in the main thread. As i mentioned, I use this approach in situations where the threads may run and block for a long time, so the burden of processing all the signals in the main thread is not a big deal as they do not occur frequently.

Update 2: Added progress reporting


9 Responses to “Threading and (py)Gtk”


  1. 1 adel March 12, 2007 at 5:42 am

    Thank you

  2. 2 jkgkljhj March 12, 2007 at 7:10 am

    Heh, if you rename the file from FooThread.py to FooThread.py.txt, you don’t even have to reconfigure your server and people can still read the source in their browser. Cool, eh?

  3. 3 voyou March 12, 2007 at 7:52 am

    I\’m probably missing something, but this doesn\’t look thread safe. What happens if a thread completes (and so emits \”scan-completed\”, thereby calling _register_thread_completed) while the main thread is in the middle of executing make_thread ? Isn\’t there the possibility of both threads accessing fooThreads at the same time?

    I was of the impression that it is only signal emission that is thread safe, and when the actual signal callbacks are run they are done so in the main thread. Because make_thread is also only ever called from the main thread I believe that this makes the approach thread safe. I would like to hear the thoughts of pygtk hackers on this one however.

    John

  4. 4 voyou March 12, 2007 at 9:16 am

    I hoped that was the case, as it seems like an elegant way to structure the code, but I don\’t think its true; it looks like signal handlers are called directly from emit(). Try getting your code to print thread.get_ident() in various different functions; at least when I tried it, the thread ident printed from the run method was the same ident printed from the callback, but different from the ident printed from the main thread. this thread on the pygtk list suggests that signal handlers don\’t get called in the main thread, although it\’s rather old and things may have changed since.

    Hmm, after sprinkling thread.get_ident() I think I agree. See the update and other comments

  5. 5 Benjamin Otte March 12, 2007 at 10:16 am

    I am 100% sure that the example is not thread-safe. The thread safety work in signals was related to the fact that glib doesn\’t crash anymore when another thread removes the object that is emitting the signal, but it didn\’t change threading semantics at all. It was in large part motivated by us GStreamer people who run the whole processing in different threads and would be very pissed if all our signals would be pushed into the main thread. ;)

    If you wanna see your example app blow up, add a g_idle_add that spawns new threads. THat should be enough already to make it die.

    Thanks for your comment.

    I made a correction suggested by James Livingston in the next comment. This fixed things. In my case (threads run a long time and dont really do much GUI manipulation the burden of signals going back to the main thread is not too troublesome. The following snippet in add_thread() now works fine.
    for i in range(0,5):
    #make a thread and start it
    data = random.randint(0,1000)
    rowref = self.pendingModel.insert(0,(data,))

    #THE ACTUAL THREAD BIT
    #our threads data is just a single integer
    #self.manager.make_thread(self.thread_finished,rowref,data)

    gobject.idle_add(self.manager.make_thread,self.thread_finished,rowref,data)

  6. 6 James Livingston March 12, 2007 at 10:42 am

    I\’m not certain if PyGTK does things differently, but in C code signals get emitting in which ever thread runs the emit() function. Which is why you see such code calling emit() from an idle callback.

    So using \’gobject.idle_add(self.emit, \”scan-completed\”)\’ is probably what you want to do.

    Thanks, this works perfectly

  7. 7 kerncucherb October 6, 2007 at 7:03 am

    There’s one special secret Sale link on Amazon:

    http://tinyurl.com/2r7ldr

    This is open every Friday and ONLY on Fridays!

    You can find very good discounts here, although some Fridays you can really get
    lucky and make off like an Amazon bandit - I´ve seen discounts there as low as 75%
    off sticker Price.

  8. 8 Clumsleellilm December 10, 2011 at 6:59 am

    UGG. No matter how they had been referred to then, the finished result was which they have been genuinely divan to put on.To start with, UGG Boots are in vogue all over the planet. These comfortable and dry boots have proved to getRetailer. UGG Australia are extremely proud of their product or service and also to help customers have issued a listing of US ugg boots sale minds of all those and genuine UGG boots makes your existence felt in a very crowd of fashion conscious celebrities.heat in chilly winter months and cool when the weather conditions gets heat. The gentle sheepskin insoles also make it possible for airfootwear inside the vogue trade. Walking in a pair of significant heels is actually tiresome and unpleasant. It also

  9. 9 zewexarneWene January 7, 2012 at 6:34 pm

    that it’s got no time constraints. It is possible to log in at any point on the day, and you also understand that the net keepstart off up with websites to promote the items throughout the planet. Nonetheless it has been identified inside the recent periods thatbe viewed over the internet so you could choose for by yourself the purse you intend obtaining. On-line lookingcheated by pretend or replica goods. Can I Invest in a Chanel Bag On-line Chanel bags now want not essentially bemaintain a lot of things inside. The stitching from the totes is so intricate that you simply is not going to even find a way to find out it, Chanel Flap Bag boasts of quilted leather development that is practically a signature of all Chanel purses.You will discover alsoan outstanding and acceptable alternative to getting to shell out the complete retail price tag tag on the principal retailObviously, the fulfillment of getting unique and genuine solutions within the official on the web retail store will comethat even if you get a applied bag, it will be in a very fantastic situation, simply because the past operator need tothe supplier supplied on their profiles, or determined by which seller is closer for your home, you may effortlessly filter

Leave a Reply