V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
toono
V2EX  ›  Python

GUI+多线程+socket+队列,怎么搞,入队阻塞!😂

  •  
  •   toono ·
    ToonoW · 2016-12-23 17:42:54 +08:00 · 3108 次点击
    这是一个创建于 2893 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看了这篇关于 GUI 情景中的 socket 编程的文章 http://www.jianshu.com/p/731a8359c2c5

    然后仿照着按照自己的业务逻辑去做,出现了以下的问题。

    现在有两个线程一个队列,一个线程负责入队,一个负责出队。 每个线程都是 1s 进行一次操作。 但是负责入队的线程经常会阻塞,就像阻塞了几秒,一下子入队好几次。

    以下的代码都是关于队列cmd_q的
    入队相关的代码

    def send_heartbeat(self, receive_dic=None):
        # 转换为连接状态
        self.api_manager.socket_is_connect = True
    
        # 开始发送心跳
        self.heartbeat_thread = threading.Thread(target=self.__send_heartbeat_timer)
        self.heartbeat_thread.start()
    
    
    def __send_heartbeat_timer(self):
        while self.api_manager.socket_is_connect:
            print("%s !!!!!!!!!!!!!put command  start!!!!!" % time.asctime(time.localtime(time.time())))
            self.api_manager.client.cmd_q.put(ClientCommand(ClientCommand.SEND, "heartbeat"))
            print("%s !!!!!!!!!!!!!put command  end!!!!!" % time.asctime(time.localtime(time.time())))
            logging.info("time: %s   send bearheart", time.asctime(time.localtime(time.time())))
            time.sleep(4) 
    

    出队相关的代码

    def run(self):
        while self.alive.isSet():
            try:
                # Queue.get with timeout to allow checking self.alive
                # print("%s !!!!!!!!!!!!!get command!!!!!" % time.asctime(time.localtime(time.time())))
    
                print("%s !!!!!!!!!!!!!get command  start!!!!!" % time.asctime(time.localtime(time.time())))
                cmd = self.cmd_q.get(True, 1)
                if (cmd.data == "heartbeat"):
                    print("%s !!!!!!!!!!!!!get command  end!!!!!" % time.asctime(time.localtime(time.time())))
                handler = self.handlers[cmd.type]
                handler(cmd)
            except queue.Empty as e:
                continue
    
    10 条回复    2016-12-31 01:08:24 +08:00
    justou
        1
    justou  
       2016-12-23 18:27:13 +08:00
    我看到入队代码有个 time.sleep(4)
    wingyiu
        2
    wingyiu  
       2016-12-24 00:09:28 +08:00
    @justou 哈哈哈
    toono
        3
    toono  
    OP
       2016-12-24 11:31:12 +08:00
    @justou 是啊,每 4s 入队一次。这有什么问题吗?😢
    hoocok
        4
    hoocok  
       2016-12-24 16:47:52 +08:00
    @toono 楼上的意思是说,你入队之后会停 4 s 再进行一次入队。但是你又说你每个线程都是 1 s 操作。是这样的吧
    toono
        5
    toono  
    OP
       2016-12-25 18:19:21 +08:00
    @hoocok 哦哦,稍微改动过代码
    iceleaf
        6
    iceleaf  
       2016-12-26 00:51:15 +08:00
    不知道你用的是什么 GUI 库,一般 GUI 库的线程问题,都应该结合 GUI 的对应 thread 函数来做,而不是直接启动 Python 的线程,这样才不会阻塞 GUI 的 event loop
    例如 pyqt4 的: https://nikolak.com/pyqt-threading-tutorial/
    toono
        7
    toono  
    OP
       2016-12-27 14:51:06 +08:00
    @iceleaf 我用的就是 pyqt4, 我后来发现的确不是入队的问题。而是像你说的线程的问题。

    我后来将程序改得简单粗暴,然后在周期性发送“ heartbeat ”的地方尝试使用了 QTimer 还是不能够解决问题了,也是在运行一段时间之后意外地阻塞一段时间。
    iceleaf
        8
    iceleaf  
       2016-12-29 18:00:35 +08:00   ❤️ 1
    @toono QTimer 利用了 Qt 的 event loop ,所以应该是不会阻塞界面的,但是 QTimer 到时间要执行的操作是一个耗时操作,这个会阻塞 QTimer 对象所在的线程,也就是主线程了,所以一般用 QThread 创建新的线程,然后在 run 函数中,创建 QTimer 的定时器,这样才不会阻塞主线程
    whatcall
        9
    whatcall  
       2016-12-30 22:10:49 +08:00
    出队的 run()里面没有 sleep ,这样如果队列是空的(或者不是空的)不是一直在运行吗? CPU 占用会比较高吧,可以插一个 sleep
    toono
        10
    toono  
    OP
       2016-12-31 01:08:24 +08:00
    @whatcall 我用得出队设置了 timeout ,所以队列为空的时候是会阻塞 1s ,队列不为空就一直工作。没错的话,应该是这样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3619 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 05:02 · PVG 13:02 · LAX 21:02 · JFK 00:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.