python thread 出现RuntimeError

1、问题来源:

        定义了一个Qthread进行网络任务,需要通过socket登陆后发送命令和接收回复消息。由于接收的可能是大文件,为了不阻塞网络,使用两个子线程进行接收和发送任务,大体代码如下:

import time
import socket
import inspect
import ctypes
import threading
from queue import Queue
from FrameDataSet import *
from PyQt5.QtCore import QThread,pyqtSignal

class TaskThread(QThread):
    sinout = pyqtSignal(dict)               # 信号类型为字典,用于状态和数据
    ConfigResvSingOut=pyqtSignal(dict)      # 信号类型为字典,用于发送设置配置后收到的返回信息

    def __init__(self):
        super(TaskThread, self).__init__()
        self.Frame = FrameData()               #打包数据帧类
        self.ConnectMark=False
        self.SendMessageQueue=Queue()          #消息发送队例,先进先出队列
        self.RecvMessageQueue=Queue()          #消息接收队例,先进先出队列
        self.SendMessageThread=threading.Thread(target=self.SendCmdMessage)     #发送消息子线程
        self.RecvMessageThread=threading.Thread(target=self.RecvCmdMessage)     #接收消息子线程


    def run(self):
        if self.TcpConnect():                    #打开socket连接上网络
            self.LoginInfo()                     #发送登陆
            self.MessageThreadStart()            #启动接收和发送消息线程
            self.WarningHeartbeat()
            while self.ConnectMark:
                self.WarningHeartbeat()          #心跳
                self.ReturnMessageProcessing()   #返回消息处理
                
    
    def LoginInfo(self):                         #登陆
        """函数代码"""
     
    
    def WarningHeartbeat(self):                  
        """函数代码"""
    
    def ReturnMessageProcessing(self):#返回消息处理函数
         """函数代码"""
    
    
    def MessageThreadStart(self):                #发送和接收线程启动
        print("启用消息发送和接收线程") 
        self.SendMessageThread.start()           #启用命令发送子线程
        self.RecvMessageThread.start()           #启用命令接收子线程
        
    
    
    def TcpConnect(self):                        #连接网络
        try:
            self.tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcpSock.connect(self.Addr)
            print("尝试连接")
            self.ConnectMark = True
            return True
        except:
            print("尝试连接失败,关闭链接")
            self.CloseConnect()
            return False
    
    
    
    def CloseConnect(self):
        print("启用TaskThread CloseConnect关闭连接")
        self.ConnectMark = False
        self.SendMessageMark = False
        self.RecvMessageMark = False
        self.SendMessageThread.join()
        self.RecvMessageThread.join()
        self.tcpSock.close()
        print("链接已断开")


2、问题:

        代码调用运行后,连接上后断开,再次连接,一直提示RuntimeError: threads can only be started once错误

3、问题原因

        网上搜python线程相关资料,有个关于线程的说法是每个线程必须只能调用一次,也就是说只能start一次

这里写图片描述

        而从我的定义来看,在初始化的时候就定义了线程,所以再次调用,这个线程就不能再被start了。

4、问题解决,将线程定义在启用线程的函数中,即:

import time
import socket
import inspect
import ctypes
import threading
from queue import Queue
from FrameDataSet import *
from PyQt5.QtCore import QThread,pyqtSignal

class TaskThread(QThread):
    sinout = pyqtSignal(dict)               # 信号类型为字典,用于状态和数据
    ConfigResvSingOut=pyqtSignal(dict)      # 信号类型为字典,用于发送设置配置后收到的返回信息

    def __init__(self):
        super(TaskThread, self).__init__()
        self.Frame = FrameData()               #打包数据帧类
        self.ConnectMark=False
        self.SendMessageQueue=Queue()          #消息发送队例,先进先出队列
        self.RecvMessageQueue=Queue()          #消息接收队例,先进先出队列


    def run(self):
        if self.TcpConnect():                    #打开socket连接上网络
            self.LoginInfo()                     #发送登陆
            self.MessageThreadStart()            #启动接收和发送消息线程
            self.WarningHeartbeat()
            while self.ConnectMark:
                self.WarningHeartbeat()          #心跳
                self.ReturnMessageProcessing()   #返回消息处理
                
    
    def LoginInfo(self):                         #登陆
        """函数代码"""
     
    
    def WarningHeartbeat(self):                  
        """函数代码"""
    
    def ReturnMessageProcessing(self):#返回消息处理函数
         """函数代码"""
    
    
    def MessageThreadStart(self):                #发送和接收线程启动
        print("启用消息发送和接收线程") 
        self.SendMessageThread=threading.Thread(target=self.SendCmdMessage)     #发送消息子线程,不能在初始化时定义,否则会出现RuntimeError错误
        self.RecvMessageThread=threading.Thread(target=self.RecvCmdMessage)     #接收消息子线程,不能在初始化时定义,否则会出现RuntimeError错误

        self.SendMessageThread.start()           #启用命令发送子线程
        self.RecvMessageThread.start()           #启用命令接收子线程

        
    
    
    def TcpConnect(self):                        #连接网络
        try:
            self.tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcpSock.connect(self.Addr)
            print("尝试连接")
            self.ConnectMark = True
            return True
        except:
            print("尝试连接失败,关闭链接")
            self.CloseConnect()
            return False
    
    
    
    def CloseConnect(self):
        print("启用TaskThread CloseConnect关闭连接")
        self.ConnectMark = False
        self.SendMessageMark = False
        self.RecvMessageMark = False
        self.SendMessageThread.join()
        self.RecvMessageThread.join()
        self.tcpSock.close()
        print("链接已断开")
 

        
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值