Pyqt Emit Signal From Threading Thread
Solution 1:
There are two main problems with your examples.
Firstly, the object that emits the signals is created in the main/gui thread, so any signals its emits will not be cross-thread, and hence not thread-safe. The obvious solution to this is to create the signalling object inside the target function of the worker thread - which means there must be a separate instance for each thread.
Secondly, the while-loop inside the target function is never terminated, which means every ThreadedCopy
object will be kept alive after the current copy operation is complete. Since all these objects share the same queue, the behaviour will become unpredictable if any attempt is made to repeat the copy operation. The obvious solution to this is to break out of the while-loop once the queue is empty.
Below is a re-write of MultithreadedCopy_5.py which should solve these issues. However, as stated in the comments, I would still strongly recommend using QThread
rather than python threads in this scenario, as it is likely to provide a much more robust and more easily maintainable solution.
import Queue, threading
from PyQt4 import QtCore
import shutil
import profile
fileQueue = Queue.Queue()
classCommunicate(QtCore.QObject):
progressSignal = QtCore.pyqtSignal(int)
classThreadedCopy:
totalFiles = 0
copyCount = 0
lock = threading.Lock()
def__init__(self, inputList, progressBar="Undefined"):
self.progressBar = progressBar
self.totalFiles = len(inputList)
printstr(self.totalFiles) + " files to copy."
self.threadWorkerCopy(inputList)
defCopyWorker(self):
c = Communicate()
c.progressSignal.connect(self.updateProgressBar)
whileTrue:
try:
fileName = fileQueue.get(False)
except Queue.Empty:
breakelse:
shutil.copy(fileName[0], fileName[1])
with self.lock:
self.copyCount += 1
percent = (self.copyCount * 100) / self.totalFiles
c.progressSignal.emit(percent)
fileQueue.task_done()
defthreadWorkerCopy(self, fileNameList):
if fileQueue.empty():
for i inrange(16):
t = threading.Thread(target=self.CopyWorker)
t.daemon = True
t.start()
for fileName in fileNameList:
fileQueue.put(fileName)
fileQueue.join()
defupdateProgressBar(self, percent):
self.progressBar.setValue(percent)
Solution 2:
The main problem is the delay of time between sending the signal and receiving, we can reduce that time using processEvents()
:
You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file).
defCopyWorker(self):
whileTrue:
fileName = fileQueue.get()
shutil.copy(fileName[0], fileName[1])
fileQueue.task_done()
with self.lock:
self.copyCount += 1print(self.copyCount)
percent = (self.copyCount * 100) / self.totalFiles
self.c.progressSignal.emit(percent)
QtCore.QCoreApplication.processEvents()
Post a Comment for "Pyqt Emit Signal From Threading Thread"