本組的安卓自動化測試軟件中,在測試開始前須要進行鏈接設備的操做,以下圖左側的按鈕python
後端MonkeyRunner
相關操做的程序中提供了connect()
函數來供客戶端使用,調用該函數會等待鏈接,並在鏈接最多5s沒有相應以後提示鏈接失敗。可是在客戶端未加處理直接調用的時候,整個客戶端都會卡死來等待函數的進行,這樣會形成不好的用戶體驗,所以試圖採用多線程的方式來解決。後端
最初的解決方案是採用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()
就這樣能夠初步實現如下效果:點擊鏈接之後按鈕變成不可用,按鈕文本變爲「鏈接中...」 直到鏈接完成函數
可是這樣的實現效果是有侷限性的,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