On 04 April 2003, Jon Trowbridge said:
> That set, allow me to offer a suggestion: you can make your life a lot
> easier by not making gtk calls from threads.  Instead, do all of your
> gtk calls from inside of one-shot idle functions launched from inside
> threads.

Great tip -- I've rewritten the code yet again, and it seems to work
now.  Mostly.  (While the eject ioctl() is running in a background
thread, the GUI is not responsive -- rather, events are buffered and
replayed when the ioctl() returns and the background thread finishes.
However, if I replace the ioctl() with a sleep(), then the GUI responds
exactly as I expect.  So I'm inclined to blame this on Linux rather than
GTK: perhaps a blocking ioctl() blocks *all* threads of the current
process, rather than just the thread that made the call.  In that case,
putting the CD-ROM eject/close ioctl() calls in a background thread is
pointless.  Sigh.  Well, it should still help for CDDB lookups...)

> Your "eject" example could be handled by code like this:

For the record, here's how I did it (roughly):

    # setup the GUI
    def __init__ (self):
        # ...
        self.eject_button.connect("clicked", self.start_eject)

    # ...later on...
    def start_eject (self, widget):
        # First update the GUI to reflect what we're about to do.
        ebutton = self.eject_button
        ebutton.set_sensitive(False)
        if self.cdrom.tray_open:        # will close the drive tray
            status = "Closing CD-ROM drive tray..."
            ebutton.set_label("Eject")
        else:                           # will eject the disc
            status = "Ejecting CD..."
            ebutton.set_label("Close")

        self.statusbar.push(self.statusbar.get_context_id(""),
                            status)
        gtk.mainiteration()

        # And then launch the thread that actually does it.
        print "launching eject/close thread..."
        thread = Thread(name="cdrom-eject", target=self.eject_cd)
        thread.start()

    def eject_cd (self):
        print "eject/close thread (%r) starting" % get_thread_id()
        if self.cdrom.tray_open:        # close the drive tray
            self.cdrom.closetray()
        else:
            self.cdrom.eject()
        gtk.idle_add(self.eject_done)

    def eject_done (self):
        print "eject_done(): thread %r updating widgets" % get_thread_id()
        self.eject_button.set_sensitive(True)
        self.statusbar.pop(self.statusbar.get_context_id(""))

Thanks!

        Greg
-- 
Greg Ward <[EMAIL PROTECTED]>                         http://www.gerg.ca/
Moderation is for monks.
_______________________________________________
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to