繁体   English   中英

PyQt5:在线程仍在运行时销毁

[英]PyQt5 : Destroyed while thread is still running

尝试添加异常,当服务器断开时程序(客户端)应该怎么做。

这个想法很简单。 如果服务器关闭 - 客户端应尝试连接到服务器,直到服务器打开。

当服务器关闭时 - 程序尝试连接。 但是当我打开服务器时,客户端已连接,然后连接断开,在客户端应用程序中我看到 - QThread:在线程仍在运行时被破坏这是我想要的简单示例(客户端的最小可重现示例):

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import socket


class ListeningThread(QtCore.QThread):
    mysignal = QtCore.pyqtSignal(str)
    def __init__(self, server_socket, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.server_socket = server_socket
        self.message = None

    def run(self):
        try:
            while True:
                    self.message = self.server_socket.recv(4096)
                    self.mysignal.emit(self.message.decode('utf-8'))
        except:
             Push()

class Push(QtWidgets.QMainWindow):
    def __init__(self):
        super(Push, self).__init__()
        print('now connecting...')
        self.connect_server()
    def connect_server(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.server_socket.connect(('127.0.0.1', 5555))
            self.message_monitor = ListeningThread(self.server_socket)
            self.message_monitor.mysignal.connect(self.init_UI)
            self.message_monitor.start()
        except:
            Push()

    def init_UI(self, message):
        print(message)

app =QtWidgets.QApplication([])
application = Push()
sys.exit(app.exec_())

我在 ListeningThread 中尝试过:

 class ListeningThread(QtCore.QThread):
    mysignal = QtCore.pyqtSignal(str)
    def __init__(self, server_socket, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.server_socket = server_socket
        self.message = None

    def run(self):
        try:
            while not self.isInterruptionRequested():
                    self.message = self.server_socket.recv(4096)
                    self.mysignal.emit(self.message.decode('utf-8'))
        except:
            print('error in thread')
            self.requestInterruption()
            self.wait()
            Push()

但问题还是一样。 我想我应该在 Push.connect_server 开始之前关闭线程,但我不知道如何。

对于最小的可重现示例,您可以使用该服务器:

import socket
import threading

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 5555))
server_socket.listen()
clients = []

def accept_socket():
    while True:
        client_socket, addr = server_socket.accept()
        print(f'connection from {addr}')
        print(client_socket)
        if client_socket not in clients:
            clients.append(client_socket)

def sending_message(clients, data):
    for client_socket in clients:
        try:
            client_socket.send(data.encode("utf-8"))
        except:
            pass

accept_thread = threading.Thread(target= accept_socket)
accept_thread.start()


while True:
    data = input('Enter_message:\n')
    sending_message(clients, data)

问题是,当发生异常时,您正在创建一个新的“推送”object,它有一个有限的 scope,因为它是一个局部变量,因此它将被销毁,并且线程等对象也将被销毁,这就是它表示。 错误信息。

您可以使用 QTcpSocket 来通过信号以简单的方式处理 sockets 并使用 Qt 事件循环,而不是使您的生活变得复杂化处理线程(IMO 它们是最后的选择)。

from functools import cached_property
import sys

from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork


class Client(QtCore.QObject):
    messageChanged = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.socket.stateChanged.connect(self.handle_state_changed)
        self.socket.errorOccurred.connect(self.handle_error_occurred)
        self.socket.readyRead.connect(self.handle_ready_read)

    @cached_property
    def socket(self):
        return QtNetwork.QTcpSocket()

    def try_connect(self):
        self.socket.connectToHost("127.0.0.1", 5555)

    def handle_state_changed(self, state):
        print(f"state: {state}")
        if state == QtNetwork.QAbstractSocket.UnconnectedState:
            print("disconnected")
            QtCore.QTimer.singleShot(1000, self.try_connect)
        elif state == QtNetwork.QAbstractSocket.ConnectedState:
            print("connected")

    def handle_error_occurred(self, error):
        print(f"error code {error}, message: {self.socket.errorString()}")

    def handle_ready_read(self):
        codec = QtCore.QTextCodec.codecForName("UTF-8")
        message = codec.toUnicode(self.socket.readAll())
        self.messageChanged.emit(message)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.client.messageChanged.connect(self.handle_message_changed)
        self.client.try_connect()

    @cached_property
    def client(self):
        return Client()

    def handle_message_changed(self, message):
        print(f"client message: {message}")


def main():

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

暂无
暂无

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

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