2016-03-08 126 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线程中,您可以处理由分隔符分割,并保留未完成的块,直到找到下一个分隔符。