0

I have an odd problem with QThreads in (pyqt). I tested QThread with implementing run method and running an infinite loop inside it. it does not affect main thread (gui). but when I emit a signal like below pseudo code any long running loop or i/o affect on main thread and makes gui freeze.

class MyThread(QThread):
    def __init__(self , *args):
        QThread.__init__(self , *args)
        self.connect(self , SIGNAL("do_some_io(QString)") , self.doSomething)

    def doSomething(self ,  params):
        #do some large i/o and loops
        parent.emit( SIGNAL("process_done()") )


class MyDialog(QDialog):
    def __init__(self , *args):
        QThread.__init__(self , *args)
        self.Thread = MyThread(self)
        self.Thread.start()
        self.connect(self.btn , SIGNAL("clicked()") , self.buttonClicked)
        self.connect(self , SIGNAL("process_done()") , self.showMsgBox)

    def buttonClicked(self):
        self.Thread.emit( SIGNAL("do_some_io(QString)") , "param" )

    def showMsgBox(self):
        #show messagebox
Joshua D. Boyd
  • 4,808
  • 3
  • 29
  • 44
SantaXYZ
  • 27
  • 1
  • 7
  • When you say freeze, do you mean a blip, for a few seconds, or apparently forever? – Joshua D. Boyd Jan 16 '15 at 20:18
  • it hangs until the i/o or any blocking process finished – SantaXYZ Jan 16 '15 at 20:25
  • @SantaXYZ. If you understand why you need to reimplement `run`, and know that it works as expected, then why the heck did you change it? What are you actually trying to achieve? – ekhumoro Jan 16 '15 at 21:57
  • 1
    [This SO post](http://stackoverflow.com/questions/20752154/pyqt-connecting-a-signal-to-a-slot-to-start-a-background-operation) may be of some use to you. As well as demonstrating the preferred way of using `QThread`s by using `moveToThread()`, it also shows a pitfall in the order in which you connect signals/slots if you don't decorate with `@pyqtSlot()`. I'm unclear whether a similar problem is happening here because you are using the [old-style](http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html) way to connect signals to slots. – three_pineapples Jan 17 '15 at 02:49
  • @three_pineapples thank you. i read the post you linked. i understand the problem is `connection type` detecting with pyqt. in other hand if i want to use new style signals and slots i need to define all signals in base class (because of mro) and for that i need to make huge changes in my code. is there any quick fix for this problem? – SantaXYZ Jan 17 '15 at 12:39
  • Well I've tried to make it work, but can't do it with old-style signals/slots. Whatever I do, your `doSomething` method is executed in the MainThread. I even tried putting it in a `QObject` and using `moveToThread()`. Nothing works using the old-style signals. **But**, as soon as I switch to using a new style signal, the threading works properly. Sorry that I can't be more helpful. – three_pineapples Jan 18 '15 at 04:06
  • @three_pineapples i switched to new style signals and there are many problems here (not supporting multiple inheritance by qt and ...). thank you – SantaXYZ Jan 19 '15 at 16:39

1 Answers1

0

This is because when you emit do_some_io, doSomething is executed in the GUI thread. In your connect calls, you need to set the connection type to QueuedConnection. That will cause the message to be added as an event to the receiving thread event queue and it will then run the signal in the receiving thread instead of the sending thread.

See: http://doc.qt.io/qt-5/qt.html#ConnectionType-enum

Joshua D. Boyd
  • 4,808
  • 3
  • 29
  • 44
  • thank you. but i changed connect method in **MyThread** like `self.connect(self , SIGNAL("do_some_io(QString)") , self.doSomething , Qt.QueuedConnection)` and still not working. i'm using PyQt4 – SantaXYZ Jan 16 '15 at 21:26
  • of course i have many connect calls like this but i changed one of them and that not worked (the one that cause freezing). – SantaXYZ Jan 16 '15 at 21:34
  • thank you. i understood the problem is `connection type` detecting with pyqt. but why when i changed my connection type to `QueuedConnection` it still does not work? – SantaXYZ Jan 17 '15 at 12:40
  • could you please give me an example of how to emit a background thread signal from gui thread and how to emit a gui thread signal from background thread? – SantaXYZ Jan 17 '15 at 15:53
  • because your answers related to my problems and helps me it's accepted. – SantaXYZ Jan 19 '15 at 16:39