UI will be blocked if creating a message dialog by emitting a signal

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

UI will be blocked if creating a message dialog by emitting a signal

Todong Ma
Hi, everyone

I met a problem that UI will be blocked forever if I emit a signal from a thread to create a message dialog.
Following code will reproduce the issue, please let me give a short explanation: AThread thread defines a custom signal named "ASignal", and the signal handler is aSignal() function of MainWindow class. The aSignal() function is used to display a message dialog. Emitting "ASignal" signal will display the message dialog successfully but the UI is blocked forever.
import gtk
import gobject
import threading

class AThread(threading.Thread, gobject.GObject):
    __gsignals__ = {
        'ASignal': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
    }
    def __init__(self):
        threading.Thread.__init__(self)
        gobject.GObject.__init__(self)

    def run(self):
        self.emit('ASignal')

class MainWindow(gtk.Window):
    def aSignal(self, obj):
        dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, 'asdfasf')
        dialog.run()
        dialog.destroy()

gobject.threads_init()

w = MainWindow()

t = AThread()
t.connect('ASignal', w.aSignal)
t.start()

gtk.main()

Any suggestion is appreciated.

Thanks,

_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: UI will be blocked if creating a message dialog by emitting a signal

Niklas Koep
Emitting signals from a thread will run the handler in the same thread. You shouldn't call gtk functions from a thread other than the main one. If you insist on doing so you have to make sure to acquire the GDK lock first by wrapping your code in gtk.gdk.threads_enter() ... gtk.gdk.threads_leave() calls. In this case you also have to call gtk.gdk.thread_init() as otherwise the main loop will never release the GDK lock. The easier solution is to push the signal emission to the main thread by replacing self.emit('ASignal') with gobject.idle_add(self.emit, 'ASignal') which guarantees the handler will also run in the main thread (which already has the GDK lock).

Regards.


On Thu, Jul 25, 2013 at 4:56 PM, Todong Ma <[hidden email]> wrote:
Hi, everyone

I met a problem that UI will be blocked forever if I emit a signal from a thread to create a message dialog.
Following code will reproduce the issue, please let me give a short explanation: AThread thread defines a custom signal named "ASignal", and the signal handler is aSignal() function of MainWindow class. The aSignal() function is used to display a message dialog. Emitting "ASignal" signal will display the message dialog successfully but the UI is blocked forever.
import gtk
import gobject
import threading

class AThread(threading.Thread, gobject.GObject):
    __gsignals__ = {
        'ASignal': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
    }
    def __init__(self):
        threading.Thread.__init__(self)
        gobject.GObject.__init__(self)

    def run(self):
        self.emit('ASignal')

class MainWindow(gtk.Window):
    def aSignal(self, obj):
        dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, 'asdfasf')
        dialog.run()
        dialog.destroy()

gobject.threads_init()

w = MainWindow()

t = AThread()
t.connect('ASignal', w.aSignal)
t.start()

gtk.main()

Any suggestion is appreciated.

Thanks,

_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/


_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: UI will be blocked if creating a message dialog by emitting a signal

Todong Ma
Thanks a lot, it works now! So far I'm using a really stupid method: using gobject.timeout_add() to check a global flag variable every 0.1 seconds, if the flag is set, the message dialog will be shown.. But now they can be fixed:)

On 2013/7/25 23:15, Niklas Koep wrote:
Emitting signals from a thread will run the handler in the same thread. You shouldn't call gtk functions from a thread other than the main one. If you insist on doing so you have to make sure to acquire the GDK lock first by wrapping your code in gtk.gdk.threads_enter() ... gtk.gdk.threads_leave() calls. In this case you also have to call gtk.gdk.thread_init() as otherwise the main loop will never release the GDK lock. The easier solution is to push the signal emission to the main thread by replacing self.emit('ASignal') with gobject.idle_add(self.emit, 'ASignal') which guarantees the handler will also run in the main thread (which already has the GDK lock).

Regards.


On Thu, Jul 25, 2013 at 4:56 PM, Todong Ma <[hidden email]> wrote:
Hi, everyone

I met a problem that UI will be blocked forever if I emit a signal from a thread to create a message dialog.
Following code will reproduce the issue, please let me give a short explanation: AThread thread defines a custom signal named "ASignal", and the signal handler is aSignal() function of MainWindow class. The aSignal() function is used to display a message dialog. Emitting "ASignal" signal will display the message dialog successfully but the UI is blocked forever.
import gtk
import gobject
import threading

class AThread(threading.Thread, gobject.GObject):
    __gsignals__ = {
        'ASignal': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
    }
    def __init__(self):
        threading.Thread.__init__(self)
        gobject.GObject.__init__(self)

    def run(self):
        self.emit('ASignal')

class MainWindow(gtk.Window):
    def aSignal(self, obj):
        dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, 'asdfasf')
        dialog.run()
        dialog.destroy()

gobject.threads_init()

w = MainWindow()

t = AThread()
t.connect('ASignal', w.aSignal)
t.start()

gtk.main()

Any suggestion is appreciated.

Thanks,

_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/



_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: UI will be blocked if creating a message dialog by emitting a signal

catalinfest@gmail.com
In reply to this post by Todong Ma
You can try this webpage where are some example and help .

--
python-catalin.blogspot.com
www.free-tutorials.org

_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/