我试图从多个线程更新pyqt QProgressBar,据我所知,最好的方法是将信号发送回主GUI线程(我尝试将QProgressBar对象传递给工作线程,尽管它看起来确实有效,但在解释器中收到了大量警告)。在下面的代码中,我设置了一个progressSignal信号,并将其连接到一个线程上,该线程(目前)只打印所发出的任何内容。然后我从每个线程发出总百分比。我知道这是在线程外工作的,它只在第47行抛出一个随机的emit,它确实通过了。然而,第36行的发射不会触发任何东西,所以它似乎永远无法通过。。。在
import Queue, threading
from PyQt4 import QtCore
import shutil
import profile
fileQueue = Queue.Queue()
class Communicate(QtCore.QObject):
progressSignal = QtCore.pyqtSignal(int)
class ThreadedCopy:
totalFiles = 0
copyCount = 0
lock = threading.Lock()
def __init__(self, inputList, progressBar="Undefined"):
self.totalFiles = len(inputList)
self.c = Communicate()
self.c.progressSignal.connect(self.updateProgressBar)
print str(self.totalFiles) + " files to copy."
self.threadWorkerCopy(inputList)
def CopyWorker(self):
while True:
self.c.progressSignal.emit(2000)
fileName = fileQueue.get()
shutil.copy(fileName[0], fileName[1])
fileQueue.task_done()
with self.lock:
self.copyCount += 1
percent = (self.copyCount * 100) / self.totalFiles
self.c.progressSignal.emit(percent)
def threadWorkerCopy(self, fileNameList):
for i in range(16):
t = threading.Thread(target=self.CopyWorker)
t.daemon = True
t.start()
for fileName in fileNameList:
fileQueue.put(fileName)
fileQueue.join()
self.c.progressSignal.emit(1000)
def updateProgressBar(self, percent):
print percent
更新:
这是一个带有图形用户界面的示例。这一个运行,但非常不稳定,它经常崩溃,用户界面做一些奇怪的事情(进度条没有完成,等等)
在主.py以下内容:
^{pr2}$多线程副本_5.py:
import Queue, threading
from PyQt4 import QtCore
import shutil
import profile
fileQueue = Queue.Queue()
class Communicate(QtCore.QObject):
progressSignal = QtCore.pyqtSignal(int)
class ThreadedCopy:
totalFiles = 0
copyCount = 0
lock = threading.Lock()
def __init__(self, inputList, progressBar="Undefined"):
self.progressBar = progressBar
self.totalFiles = len(inputList)
self.c = Communicate()
self.c.progressSignal.connect(self.updateProgressBar, QtCore.Qt.DirectConnection)
print str(self.totalFiles) + " files to copy."
self.threadWorkerCopy(inputList)
def CopyWorker(self):
while True:
fileName = fileQueue.get()
shutil.copy(fileName[0], fileName[1])
fileQueue.task_done()
with self.lock:
self.copyCount += 1
percent = (self.copyCount * 100) / self.totalFiles
self.c.progressSignal.emit(percent)
def threadWorkerCopy(self, fileNameList):
for i in range(16):
t = threading.Thread(target=self.CopyWorker)
t.daemon = True
t.start()
for fileName in fileNameList:
fileQueue.put(fileName)
fileQueue.join()
def updateProgressBar(self, percent):
self.progressBar.setValue(percent)
#profile.run('ThreadedCopy()')
主要问题是发送信号和接收信号之间的时间延迟,我们可以使用^{} 来缩短时间:
你的例子有两个主要问题。在
首先,发出信号的对象是在main/gui线程中创建的,因此它发出的任何信号都不会是跨线程的,因此不是线程安全的。显而易见的解决方案是在工作线程的目标函数内部创建信令对象,这意味着每个线程都必须有一个单独的实例。在
其次,目标函数中的while循环永远不会终止,这意味着在当前复制操作完成后,每个
ThreadedCopy
对象都将保持活动状态。由于所有这些对象共享同一个队列,如果试图重复复制操作,行为将变得不可预测。显而易见的解决方案是,一旦队列为空,就跳出while循环。在下面是对MultithreadedCopy_5.py的重写,应该可以解决这些问题。但是,正如评论中所述,我仍然强烈建议在这个场景中使用
QThread
而不是python线程,因为它可能提供一个更健壮、更易于维护的解决方案。在相关问题 更多 >
编程相关推荐