samedi 1 novembre 2014

Why main event loop gets frozen if private slot is called from background thread?


Vote count:

0




I'm developing GUI application using python and PySide. I need to run long backgroung task in a separate thread. For threading I decided to use QThread according to the 'correct' approach without subclassing from if (see http://ift.tt/OU4LtR). So, to run my long task in background I just connect thread's signal 'started' to a method with performes long task.


For some reason, my program didn't work as expected. I spent several hours before I found that if I rename slot name to be 'public' (remove underscores) everything starts to work as expected. I wonder what is wrong with the private slot? Seems that for some reason main event loop doesn't work while private slot is in progress, although I can see that it is executed in a thread different from main thread (see program output below).


Here is an example which reproduces the problem:



from PySide.QtCore import QThread, QObject, QCoreApplication, QTimer
import time
import sys

class BackgroundWorker(QObject):
def __init__(self):
QObject.__init__(self)

def __process(self):
self.process()

def process(self):
print 'Background thread:', QThread.currentThread()
for i in xrange(0, 5):
print 'In background thread', i
time.sleep(1)
self.thread.quit()

def start(self):
self.thread = QThread()
self.moveToThread(self.thread)
#self.thread.started.connect(self.process) # <---- Case 1: This works as expected
self.thread.started.connect(self.__process) # <---- Case 2: Main event loop freezes.
self.thread.finished.connect(app.quit)
self.thread.start()

def main_thread():
print 'Main thread:', QThread.currentThread()
for i in xrange(0, 5):
print 'In main thread', i
time.sleep(1)

if __name__ == '__main__':
app = QCoreApplication(sys.argv)
bw = BackgroundWorker()
QTimer.singleShot(0, bw.start)
QTimer.singleShot(100, main_thread)
app.exec_()


In the code above in method 'BackgroundWorker.start' there are two lines for connecting thread 'started' signal to slots. 'Case 1' line works as expected (public slot connected), but 'case 2' line - not (private slot connected).


Program output for case 1:



Background thread: <PySide.QtCore.QThread object at 0x02161738>
In background thread 0
Main thread: <PySide.QtCore.QThread object at 0x021616E8>
In main thread 0
In background thread 1
In main thread 1
In background thread 2
In main thread 2
In background thread 3
In main thread 3
In background thread 4
In main thread 4


Program output for case 2:



Background thread: <PySide.QtCore.QThread object at 0x021916E8>
In background thread 0
In background thread 1
In background thread 2
In background thread 3
In background thread 4
Main thread: <PySide.QtCore.QThread object at 0x02191788>
In main thread 0
In main thread 1
In main thread 2
In main thread 3
In main thread 4


I suspect this is somehow related to signal/slot implementation in PySide, but I haven't managed to find any bug report or something related to a behavior I observe.


PySide version is 1.2.2, python version is 2.6.6



asked 30 secs ago







Why main event loop gets frozen if private slot is called from background thread?

Aucun commentaire:

Enregistrer un commentaire