2016-03-08 72 views
0

我正在寫一些代碼,使用標準線程,Queue,QThreads在pyqt和套接字。 基本上我打開一個套接字服務器,並從其他程序接收數據。我在這裏有幾個問題。PyQT線程和Socketing安全,並捕捉多個信號

  1. 即使我試圖正常地殺死我的線程,我的程序似乎仍然關閉。避免這種情況的唯一方法是將特定線程設置爲守護進程。我在做什麼來殺死它,正在使用我將在我的GUI的closeEvent()中設置的成員( self._terminate = threading.Event())。 我的線程會不斷檢查這個終止並返回它是否存在。 我的套接字也將被關閉 - 子連接將調用shutdown(),並且主服務器會通過發送一些假數據來推送線程上的偵聽循環,這也會終止。

所有這些,正如我所提到的,發生在我的GUI的closeEvent()中,但是當我以這種方式設置時,它會在退出時掛起。該程序將隱藏但殼仍然活躍,並沒有死。通過將保存服務器套接字的線程設置爲守護進程,一切都可以關閉。

這樣做很安全,因爲我沒有將任何內容寫入文件或從文件中讀取,對嗎?

  1. 問題的第二部分是我設置了QThread來收集來自我的PriorityQueue的任何傳入數據,並根據需要將信號發送到GUI。它會將所有可用數據每次做檢查,事情大致是這樣的時間:

- 然後

class DataCollector(QtCore.QThread): 
    dataSig = QtCore.SIGNAL('data') 

    def __init__(self, q): 
     super(DataCollector, self).__init__(None) 

     self.check_time = 5 
     self.scan_time = 0.2 
     self.last_check = time.time() - self.check_time 
     self.queue = q 
     self._terminate = False 

    def run(self): 
     while True: 
      if self._terminate: 
       return 

      time.sleep(self.scan_time) 

      if time.time() > self.last_check + self.check_time: 
       while self.queue.empty is False: 
        data = self.queue.get() 
        self.emit(self.dataSig, data)    

我的主界面會趕上這些信號,並在我的測試 - 將它們添加到最後一個控件。

在我的測試中,在一段時間後,測試數據將得到合併成一條線 - 如果我的隊列包含例如

  • 測試
  • 再次測試
  • 測試更多

我很快發出這些信號,直到隊列被清空,偶爾我的列表小部件會有一個雙入口,例如:

  • 測試
  • 再次測試
  • 測試更多
  • 測試
  • 再次測試
  • 測試更多
  • 測試
  • 測試againtest更多******

這是因爲我發射太快了嗎?什麼可能會導致這種情況,以及哪些可能的修復?

感謝您的任何和所有的投入!

+0

我認爲這將很難回答1)沒有看到'closeEvent()'方法和線程的相關代碼。對於2),我建議在你的'QThread'中嘗試切換到[新樣式信號和插槽](http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html),看看是否解決了這個問題。 –

+0

明天發佈關閉事件 - 是的,生病嘗試新的信號和插槽系統,看看是否是這樣,但我有一種感覺,它涉及從同一線程一次發射太多。 - 丁子 –

+0

@Aboogie這不是我的問題,我只是編輯它來改善內容。你需要問問Alex。 –

回答

0

我懷疑它與信號的速度無關,sicne QT內部以隊列類型的方式處理這些信號。 我認爲正在發生的事情是,你的印象是,當你從套接字中調用send或sendall時,所有數據都作爲一個數據包發送,而當你recv(字節)時,它將接收到一個完整的數據包一次。

事實並非如此。數據以時尚流的形式發送,所以最終可能會出現塊或組合結果。有兩種方法解決此問題:

一個,在每個數據包的話說,下面的數據是多長時間開始發送一些數據,和recv那麼多 或者我傾向於使用: 用delmiter發送數據,即:如果您的分隔符是|!|,則發送的數據將是 test |!| testAgain |!| testMore |!|

然後在接收線程上處理它。例如,該流可能首次通過: test |!| testA 其次是增益|!| testMore |!| 第二次。

在yoru線程中,您可以處理由分隔符分割,並保留未完成的塊,直到找到下一個分隔符。