Skip to content Skip to sidebar Skip to footer

How To Return Value From Function Running By Qthread And Queue

Please explain how do we send/receive data from Thread managed by Queue.... First I subclass 'QThread' defining its run() method which is started when QThread's.start() is called:

Solution 1:

In normal circumstances you'd use a result queue to send results back, and then have some other thread running that waits for the results:

classSimpleThread(QtCore.QThread):
    def__init__(self, queue, result_queue, parent=None):
        QtCore.QThread.__init__(self, parent)      
        self.queue=queue
        self.result_queue = result_queue

    defrun(self):
        whileTrue:
            arg=self.queue.get() 
            self.fun(arg)    
            self.queue.task_done()

    deffun(self, arg):
        for i inrange (3):
            print'fun: %s'%i
            self.sleep(1)
        self.result_queue.put(arg+1)

defhandle_results(result_queue):
   whileTrue:
       result = result_queue.get()
       print("Got result {}".format(result))

Main thread:

self.queue=queue.Queue()
self.result_queue = queue.Queue()

result_handler = threading.Thread(target=handle_results, self.result_queue)
for i in range(2):
    thread=SimpleThread(self.queue, self.result_queue)
    thread.start()

Doing it this way will keep you from blocking the GUI's event loop while you wait for the results. Here's what the equivalent would look like with multiprocessing.pool.ThreadPool:

from multiprocessing.pool import ThreadPool
import time


def fun(arg):
    for i in range (3):
        print 'fun: %s'%i
        time.sleep(1)
    return arg+1

def handle_result(result):
   print("got result {}".format(result))

pool = ThreadPool(2)
pool.map_async(fun, [1,2,3], callback=handle_result)

Which is a lot simpler. It internally creates a result handling thread, which will automatically call handle_result for you when fun completes.

That said, you're using QThread, and you want the results to update GUI widgets, so you really want your results to be sent back to the main thread, not to a result handling thread. In that case, it makes sense to use Qt's signaling system, so that you can safely update the GUI when you receive the result:

from PyQt4 import QtCore, QtGui
import sys
import Queue as queue

classResultObj(QtCore.QObject):
    def__init__(self, val):
        self.val = val

classSimpleThread(QtCore.QThread):
    finished = QtCore.pyqtSignal(object)

    def__init__(self, queue, callback, parent=None):
        QtCore.QThread.__init__(self, parent)      
        self.queue = queue
        self.finished.connect(callback)

    defrun(self):
        whileTrue:
            arg = self.queue.get() 
            if arg isNone: # None means exitprint("Shutting down")
                return
            self.fun(arg)    

    deffun(self, arg):
        for i inrange(3):
            print'fun: %s' % i
            self.sleep(1)
        self.finished.emit(ResultObj(arg+1))


classAppWindow(QtGui.QMainWindow):
    def__init__(self):
        super(AppWindow, self).__init__()
        mainWidget = QtGui.QWidget()
        self.setCentralWidget(mainWidget)
        mainLayout = QtGui.QVBoxLayout()
        mainWidget.setLayout(mainLayout)  
        button = QtGui.QPushButton('Process')
        button.clicked.connect(self.process)
        mainLayout.addWidget(button)

    defhandle_result(self, result):
        val = result.val
        print("got val {}".format(val))
        # You can update the UI from here.defprocess(self):
        MAX_CORES=2
        self.queue = queue.Queue()
        self.threads = []
        for i inrange(MAX_CORES):
            thread = SimpleThread(self.queue, self.handle_result)
            self.threads.append(thread)
            thread.start()  

        for arg in [1,2,3]:
            self.queue.put(arg)

        for _ inrange(MAX_CORES): # Tell the workers to shut down
            self.queue.put(None)

app = QtGui.QApplication([])
window = AppWindow()
window.show()
sys.exit(app.exec_())

Output when the button is pushed:

fun: 0fun: 0fun: 1fun: 1fun: 2fun: 2fun: 0
got val2
got val3
Shutting down
fun: 1fun: 2
Shutting down
got val4

Post a Comment for "How To Return Value From Function Running By Qthread And Queue"