简体   繁体   English

PyQt5:线程未结束? 进程以退出代码 -1 结束

[英]PyQt5: Thread Not Ending? Process finished with exit code -1

Below code runs well and does its job.下面的代码运行良好并完成了它的工作。 However, when I exit the GUI, the python file does not finish processing.但是,当我退出 GUI 时,python 文件没有完成处理。

When I run through pycharm debug run then force terminate the debug, I get the message "Process finished with exit code -1".当我运行 pycharm 调试运行然后强制终止调试时,我收到消息“进程完成,退出代码 -1”。

Could anyone help me to find what is causing this error?谁能帮我找出导致此错误的原因?

from PyQt5 import uic
from PyQt5.QtWidgets import QWidget
from pybithumb import WebSocketManager
from PyQt5.QtCore import QThread, pyqtSignal

class OverViewWorker(QThread):
    data24Sent = pyqtSignal(int, float, int, float, int, int)
    dataMidSent = pyqtSignal(int, float, float)

    def __init__(self, ticker):
        super().__init__()
        self.ticker = ticker
        self.alive = True

    def run(self):
        wm = WebSocketManager("ticker", [f"{self.ticker}_KRW"], ["24H", "MID"])
        while self.alive:
            data = wm.get()
            if data['content']['tickType'] == "MID":
                self.dataMidSent.emit(int(data['content']['closePrice']),
                    ## Deleted
            else:
                self.data24Sent.emit(int(data['content']['closePrice']),
                    ## Deleted

    def close(self):
        self.alive = False

class OverviewWidget(QWidget):
    def __init__(self, parent=None, ticker="BTC"):
        super().__init__(parent)
        uic.loadUi("resource/overview.ui", self)

        self.ticker = ticker
        self.ovw = OverViewWorker(ticker)
        self.ovw.data24Sent.connect(self.fill24Data)
        self.ovw.dataMidSent.connect(self.fillMidData)
        self.ovw.start()

    def fill24Data(self, currPrice, volume, highPrice, value, lowPrice, PrevClosePrice):
        ## Deleted

    def fillMidData(self, currPrice, chgRate, volumePower):
        ## Deleted

    def closeEvent(self, event):
        self.ovw.close()

if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication
    app = QApplication(sys.argv)
    ob = OverviewWidget()
    ob.show()
    exit(app.exec_())

In your code, the QThread.run() method enters a while True loop, which never allows any CPU time to execute the close method and change self.alive to False, therefore that loop never ends even though you emit the close signal from the QWidget.在您的代码中,QThread.run() 方法进入了一个 while True 循环,它永远不会允许任何 CPU 时间执行 close 方法并将 self.alive 更改为 False,因此即使您从QWidget。

You are then trying to quit a thread which is still running, and that gives you the -1 return code as your QThread is forcefully killed without finishing its tasks.然后你试图退出一个仍在运行的线程,这会给你-1返回代码,因为你的 QThread 被强行杀死而没有完成它的任务。

If you add the possibility to update the alive parameter from within the loop, you can get out of this issue, but it would need the QThread to access a parameter of the QWidget, which may not be what you want.如果您添加从循环中更新活动参数的可能性,您可以摆脱这个问题,但它需要 QThread 来访问 QWidget 的参数,这可能不是您想要的。

Moreover, using QThread.wait() method may help you for synchronizing, as it will forcefully delay the exit of your QWidget until ovw returns from run.此外,使用 QThread.wait() 方法可以帮助您进行同步,因为它会强制延迟 QWidget 的退出,直到 ovw 从运行返回。 Since your -1 return code may just be due to your QApplication exiting moments before the thread finishes, synchronizing the exits will alleviate that.由于您的 -1 返回代码可能只是由于您的 QApplication 在线程完成之前退出时刻,因此同步退出将缓解这种情况。

Here is an example of that based on your code:这是基于您的代码的示例:

from PyQt5 import uic
from PyQt5.QtWidgets import QWidget
from pybithumb import WebSocketManager
from PyQt5.QtCore import QThread, pyqtSignal

class OverViewWorker(QThread):
    data24Sent = pyqtSignal(int, float, int, float, int, int)
    dataMidSent = pyqtSignal(int, float, float)

    def __init__(self, ticker, master):
        super().__init__()
        self.ticker = ticker
        self.master = master
        self.alive = True

    def run(self):
        wm = WebSocketManager("ticker", [f"{self.ticker}_KRW"], ["24H", "MID"])
        while self.alive:
            data = wm.get()
            if data['content']['tickType'] == "MID":
                self.dataMidSent.emit(int(data['content']['closePrice']),
                    ## Deleted
            else:
                self.data24Sent.emit(int(data['content']['closePrice']),
                    ## Deleted

            self.get_alive_from_master()

        # Do here anything you want in the thread before quitting.

    def get_alive_from_master(self):
        self.alive = master.ovw_alive

class OverviewWidget(QWidget):
    def __init__(self, parent=None, ticker="BTC"):
        super().__init__(parent)
        uic.loadUi("resource/overview.ui", self)

        self.ticker = ticker
        self.ovw = OverViewWorker(ticker, self)
        self.ovw.data24Sent.connect(self.fill24Data)
        self.ovw.dataMidSent.connect(self.fillMidData)
        self.ovw_alive = True
        self.ovw.start()

    def fill24Data(self, currPrice, volume, highPrice, value, lowPrice, PrevClosePrice):
        ## Deleted

    def fillMidData(self, currPrice, chgRate, volumePower):
        ## Deleted

    def closeEvent(self, event):
        self.ovw_alive = False
        self.ovw.wait()

if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication
    app = QApplication(sys.argv)
    ob = OverviewWidget()
    ob.show()
    exit(app.exec_())

Qt application exits if last window closed, if there are running threads left, it terminates them.如果最后一个 window 关闭,则 Qt 应用程序退出,如果还有正在运行的线程,则终止它们。 It can be overriden with app.setQuitOnLastWindowClosed(False) .它可以被app.setQuitOnLastWindowClosed(False)覆盖。 In that case you must call app.quit() on thread finished to terminate application.在这种情况下,您必须在线程finished时调用app.quit()以终止应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM