[技術博客]採用Qthread實現多線程鏈接等待

採用Qthread實現多線程鏈接等待

​ 本組的安卓自動化測試軟件中,在測試開始前須要進行鏈接設備的操做,以下圖左側的按鈕python

​ 後端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,致使線程莫名其妙終結,所以線程變量推薦做爲類的成員變量或者全局變量存在。code

相關文章
相關標籤/搜索