multithreading - 在PyQt中,python 后台线程带有 QThread

  显示原文与译文双语对照的内容

我有一个程序与我在PyQt中编写的gui使用的收音机接口。 显然无线电的一个主要功能是传输数据,但是要继续执行这个操作,这会导致gui挂起。 我从来没有处理过线程,我试图摆脱这些挂起使用 QCoreApplication.processEvents(). 在传输之间需要睡眠,所以,gui仍然是基于睡眠的时间,这是一个长期的睡眠。

是否有一种简单的方法来使用 QThread? 我已经找到了关于如何实现多线程的教程,但大多数都处理服务器,比需要的更高。 我真的不需要我的线程在运行时更新任何东西,我只需要启动它,让它在背景中传输。

时间: 原作者:

我创建了一个小例子,展示了 3种不同的。简单的处理线程的方法。 我希望它能帮助你找到正确的解决问题的方法。


import sys


import time



from PyQt5.QtCore import (QCoreApplication, QObject, QRunnable, QThread,


 QThreadPool, pyqtSignal)



# Subclassing QThread


# http://qt-project.org/doc/latest/qthread.html


class AThread(QThread):



 def run(self):


 count = 0


 while count <5:


 time.sleep(1)


 print("A Increasing")


 count += 1



# Subclassing QObject and using moveToThread


# http://blog.qt.digia.com/blog/2007/07/05/qthreads-no-longer-abstract


class SomeObject(QObject):



 finished = pyqtSignal()



 def long_running(self):


 count = 0


 while count <5:


 time.sleep(1)


 print("B Increasing")


 count += 1


 self.finished.emit()



# Using a QRunnable


# http://qt-project.org/doc/latest/qthreadpool.html


# Note that a QRunnable isn't a subclass of QObject and therefore does


# not provide signals and slots.


class Runnable(QRunnable):



 def run(self):


 count = 0


 app = QCoreApplication.instance()


 while count <5:


 print("C Increasing")


 time.sleep(1)


 count += 1


 app.quit()



def using_q_thread():


 app = QCoreApplication([])


 thread = AThread()


 thread.finished.connect(app.exit)


 thread.start()


 sys.exit(app.exec_())



def using_move_to_thread():


 app = QCoreApplication([])


 objThread = QThread()


 obj = SomeObject()


 obj.moveToThread(objThread)


 obj.finished.connect(objThread.quit)


 objThread.started.connect(obj.long_running)


 objThread.finished.connect(app.exit)


 objThread.start()


 sys.exit(app.exec_())



def using_q_runnable():


 app = QCoreApplication([])


 runnable = Runnable()


 QThreadPool.globalInstance().start(runnable)


 sys.exit(app.exec_())



if __name__ =="__main__":


 #using_q_thread()


 #using_move_to_thread()


 using_q_runnable()



原作者:

我修复了一个错误的例子,并且 pyqt4.8 现在也是常见的,所以我还删除了dataReady类。


# -*- coding: utf-8 -*-


import sys


from PyQt4 import QtCore, QtGui


from PyQt4.QtCore import Qt



# very testable class (hint: you can use mock.Mock for the signals)


class Worker(QtCore.QObject):


 finished = QtCore.pyqtSignal()


 dataReady = QtCore.pyqtSignal(list, dict)



 @QtCore.pyqtSlot()


 def processA(self):


 print"Worker.processA()"


 self.finished.emit()



 @QtCore.pyqtSlot(str, list, list)


 def processB(self, foo, bar=None, baz=None):


 print"Worker.processB()"


 for thing in bar:


 # lots of processing...


 self.dataReady.emit(['dummy', 'data'], {'dummy': ['data']})


 self.finished.emit()



def onDataReady(aList, aDict):


 print 'onDataReady'


 print repr(aList)


 print repr(aDict)



app = QtGui.QApplication(sys.argv)



thread = QtCore.QThread() # no parent!


obj = Worker() # no parent!


obj.dataReady.connect(onDataReady)



obj.moveToThread(thread)



# if you want the thread to stop after the worker is done


# you can always call thread.start() again later


obj.finished.connect(thread.quit)



# one way to do it is to start processing as soon as the thread starts


# this is okay in some cases... but makes it harder to send data to


# the worker object from the main gui thread. As you can see I'm calling


# processA() which takes no arguments


thread.started.connect(obj.processA)


thread.finished.connect(app.exit)



thread.start()



# another way to do it, which is a bit fancier, allows you to talk back and


# forth with the object in a thread safe way by communicating through signals


# and slots (now that the thread is running I can start calling methods on


# the worker object)


QtCore.QMetaObject.invokeMethod(obj, 'processB', Qt.QueuedConnection,


 QtCore.Q_ARG(str,"Hello World!"),


 QtCore.Q_ARG(list, ["args", 0, 1]),


 QtCore.Q_ARG(list, []))



# that looks a bit scary, but its a totally ok thing to do in Qt,


# we're simply using the system that Signals and Slots are built on top of,


# the QMetaObject, to make it act like we safely emitted a signal for


# the worker thread to pick up when its event loop resumes (so if its doing


# a bunch of work you can call this method 10 times and it will just queue


# up the calls. Note: PyQt> 4.6 will not allow you to pass in a None


# instead of an empty list, it has stricter type checking



app.exec_()



原作者:
...