• [技术博客]采用Qthread实现多线程连接等待


    采用Qthread实现多线程连接等待

    ​ 本组的安卓自动化测试软件中,在测试开始前需要进行连接设备的操作,如下图左侧的按钮

    ​ 后端MonkeyRunner相关操作的程序中提供了connect()函数来供客户端使用,调用该函数会等待连接,并在连接最多5s没有相应之后提示连接失败。但是在客户端未加处理直接调用的时候,整个客户端都会卡死来等待函数的进行,这样会造成很差的用户体验,因此试图采用多线程的方式来解决。

    采用theading实现

    ​ 最初的解决方案是采用python的threading库来实现多线程,编写了以下代码:

        def thread_waitingfor_connect(self):
            while(self.successfully_connect == None ):
                self.successfully_connect = functions_class.connect()
                #成功连接以后返回一个设备分辨率的元组(x,y)
                if(isinstance(self.successfully_connect,tuple)):
                    self.max_x = self.successfully_connect[0]
                    self.max_y = self.successfully_connect[1]
                    self.InputAssignmentButton.setEnabled(True)
                    self.connectDeviceButton.setEnabled(False)
                    self.loadButton.setEnabled(True)
                    self.connectDeviceButton.setText('已成功连接')
                    break
                    #self.connectDeviceButton.setText("重新连接")
                elif(self.successfully_connect == False):
                    self.connectDeviceButton.setEnabled(True)
                    self.successfully_connect = None
                    self.connectDeviceButton.setText('重新连接')
                    break
    

    ​ 然后连接按钮的点击信号所绑定的槽函数里加入线程启动的代码:

            self.connect_thread = threading.Thread(target = self.thread_waitingfor_connect)
            self.connect_thread.start()
    

    ​ 就这样可以初步实现以下效果:点击连接以后按钮变成不可用,按钮文本变为“连接中...” 直到连接完成

    采用Qthread实现

    ​ 但是这样的实现效果是有局限性的,UI部分代码放在线程中执行似乎不安全。而且后端提供的connect()函数在某些情况下返回时间会过长,当我想要在连接时间过久时通过QMessageBox来提示信息的时候,程序就会卡死。在Qt的编码规范中,子线程一般只用于信号的传递,不在子线程代码中直接更改UI,有助于避免程序崩溃。Qt提供了Qthread线程库来实现通过子线程来传递信号的功能。

    ​ 用Qthread重写后的连接代码:

    class WaitConnect(QtCore.QThread):
        def __init__(self, t, parent=None):
            super(WaitConnect, self).__init__(parent)
            self.t = t
            self.finished.connect(t.after_connect)#线程执行完成后发射finished信号,执行t.after_connect槽函数
        def run(self):
            self.t.successfully_connect = functions_class.connect()
            
    #in class TWindow
    #把功能代码放入单独的函数中等待完成信号
    def after_connect(self):
            if (isinstance(self.successfully_connect, tuple)):
                self.max_x = int(self.successfully_connect[0])
                self.max_y = int(self.successfully_connect[1])
                # self.rate_tuple = self.su
                self.InputAssignmentButton.setEnabled(True)
                self.connectDeviceButton.setEnabled(False)
                self.loadButton.setEnabled(True)
                self.connectDeviceButton.setText('已成功连接')
                # self.connectDeviceButton.setText("重新连接")
            elif (self.successfully_connect == False):
                self.connectDeviceButton.setEnabled(True)
                # self.successfully_connect = None
                self.connectDeviceButton.setText('重新连接')
    

    用QThread实现等待时间超过10s以后出现提示框:

    class TimeWaitThread(QtCore.QThread):
        def __init__(self,t,parent = None):
            super(TimeWaitThread,self).__init__(parent)
            self.finished.connect(t.wait_about)#完成后执行wait_about函数
        def run(self):
            self.sleep(10)
            
    #in class TWindow
    def wait_about(self):
        if(self.successfully_connect == None):
            QMessageBox.about(self,'提示','连接时间过长,请检查您的环境配置和连接状态')
            self.connectDeviceButton.setEnabled(True)
            self.successfully_connect = None
            self.connectDeviceButton.setText('重新连接')
    

    注意:QThread和threading在使用中不同的一点在于,threading的线程start以后是不会被python的gc回收的,而QThread线程如果作为局部变量,会在函数执行结束以后就被gc,导致线程莫名其妙终结,因此线程变量推荐作为类的成员变量或者全局变量存在。

  • 相关阅读:
    GC 打印日志配置
    Java查看Old代对象具体信息
    Java 进程 OOM 的排查分析(glibc 篇)
    排障 v2 堆外内存泄漏
    HotSpot VM的Native Memory Tracking
    gc日志深入解析
    排障 v1
    图和图算法js
    export与export default的区别
    leftNav
  • 原文地址:https://www.cnblogs.com/dszw/p/10920563.html
Copyright © 2020-2023  润新知