[英]Unknown error with QThread after emiting finished signal
我正在 PyQt5 中構建一個應用程序。 我的代碼中有一個計算需求很高的點需要很長時間,所以為了防止 GUI 凍結,我使用了 QThrads。 我有一個 Proces 線程來進行計算,但我使用不同的線程來給用戶反饋(在進度條的幫助下),程序實際上正在運行。 我需要這樣做,因為計算發生在塊中,所以我無法根據計算的 state 更新我的進度條。 我基於相同的方法創建了 2 個線程和 2 個工作線程,但是當我發出第二個工作線程的完成信號(表示工作已完成)時,程序崩潰並拋出錯誤而沒有解釋。 有時在調試情緒中也會發生同樣的情況。
發生相同問題的示例:
主要的:
import sys
from Workers import LoadingWorker, ProcessWorker
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar, QListWidget
class Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.clicksCount = 0
self.setupUi()
def setupUi(self):
# Create widgets
self.setWindowTitle("MRE")
self.resize(300, 150)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.progressBar = QProgressBar()
self.progressBar.setValue(0)
self.progressBar.setTextVisible(False)
self.list = QListWidget()
self.Btn = QPushButton("Do Stuff", self)
# Set the layout
layout = QVBoxLayout()
layout.addWidget(self.progressBar)
layout.addWidget(self.list)
layout.addWidget(self.Btn)
self.centralWidget.setLayout(layout)
self.data = None
self.runtime = 0
# Add callbacks
self.Btn.clicked.connect(self.btn_licked)
def btn_licked(self):
# Call functions to start threads
self.loading()
self.process()
def process(self):
# Set up process worker and get it running
self.ThreadProcess = QThread()
self.WorkerProceess = ProcessWorker()
self.WorkerProceess.moveToThread(self.ThreadProcess)
self.ThreadProcess.started.connect(self.WorkerProceess.run)
self.WorkerProceess.finished.connect(self.ThreadProcess.quit)
self.WorkerProceess.finished.connect(self.WorkerProceess.deleteLater)
self.ThreadProcess.finished.connect(self.ThreadProcess.deleteLater)
self.WorkerProceess.progress.connect(self.process_progress)
self.ThreadProcess.start()
self.ThreadProcess.finished.connect(self.process_end)
def process_end(self):
self.WorkerLoading.done = True
def process_progress(self, data, runtime):
self.data = data
self.runtime = runtime
# Some operations on data
def loading(self):
# Set up loading worker and get it running
self.ThreadLoading = QThread()
self.WorkerLoading = LoadingWorker()
self.WorkerLoading.moveToThread(self.ThreadLoading)
self.ThreadLoading.started.connect(self.WorkerLoading.run)
self.WorkerLoading.finished.connect(self.ThreadLoading.quit)
self.WorkerLoading.finished.connect(self.WorkerLoading.deleteLater)
self.WorkerLoading.finished.connect(self.ThreadLoading.deleteLater)
self.WorkerLoading.progress.connect(self.loading_progress)
self.ThreadLoading.start()
self.ThreadLoading.finished.connect(self.loading_end)
def loading_progress(self, val):
self.progressBar.setValue(val)
def loading_end(self,):
print("Stepped into loading ended")
self.list.addItem("Runtime (s): " + str(self.runtime))
self.progressBar.setValue(0)
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
工人階級:
from time import sleep
from PyQt5.QtCore import QObject, pyqtSignal
import numpy as np
from time import time
class ProcessWorker(QObject):
finished = pyqtSignal()
progress = pyqtSignal(np.ndarray, float)
def run(self):
start_time = time()
data = np.random.random(size=(50, 500000))
data = np.fft.fft(np.linalg.pinv(data))
runtime = time() - start_time
self.progress.emit(data, runtime)
self.finished.emit()
class LoadingWorker(QObject):
finished = pyqtSignal()
progress = pyqtSignal(int)
done = False
def run(self):
cnt=0
while (not self.done):
cnt+=1
if cnt==101:
cnt=0
sleep(0.1)
sleep(0.005)
self.progress.emit(cnt)
self.finished.emit()
print("loading finish sign supposedly emitted")
另一件有趣的事是,錯誤不會一直發生。 我得到的錯誤:進程以退出代碼-1073740791(0xC0000409)完成。 我試圖調試它,但我無法找出問題的原因。
當工作人員完成時,您正在刪除線程,因此您會遇到某種競爭條件:當工作人員的finished
信號發出時,線程仍在運行,您要求它退出並刪除它; 因為此時線程仍在運行,這會產生問題。
您應該在線程完成后刪除線程。
改變這個:
self.WorkerLoading.finished.connect(self.ThreadLoading.deleteLater)
對此:
self.ThreadLoading.finished.connect(self.ThreadLoading.deleteLater)
請注意,對於像這樣的簡單情況,您可以只繼承 QThread,實現它的run()
和start()
它。
這使事情變得更容易,因為您只有一個 object 可供參考。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.