如何在tkinter的主循环中处理阻塞调用/ 1-s? ZMQ / Tkinter

时间:2018-04-14 23:59:17

标签: python tkinter zeromq pyzmq

我正在使用ZeroMQ,它是一个消息库(可能是异步I / O),如果你不知道它是什么,你可以认为它类似于python中的套接字库,用于消息传递的套接字通常是在一个无限的while循环中运行,小睡眠,以保持一切凉爽。

我将代码写在一个单独的文件中,并且我有一个基于该代码分开工作的GUI,我想整合这两个代码。

但我遇到的问题是,我不能在 {内置 while True 或阻止 socket.recv() {1}} tkinter

我想接收一个阻塞的套接字 - 但我可以管理问题的这一部分, .mainloop() 套接字可以被轮询(定期检查以查看是否我们有待处理的待处理消息)或等效地您可以使用 zmq 执行同样的操作。

但问题仍然是我需要一个 zmq.DONTWAIT ,以便不断轮询套接字,比如每毫秒查看我们是否有消息。

如何在while True while True 中添加tkinter,以便我可以不断检查该套接字的状态?

我想象这样的事情:

.mainloop()

我已经检查了互联网,并在SO上遇到了解决方案,它说你可以使用小部件的After属性,但我不确定它是如何工作的。如果有人能帮助我,我将非常感激!

参考代码:

如果你没有任何未决的消息让我们在循环中前进,

while True: update_gui() # contains the mainloop and all GUI code check_socket() # listener socket for incoming traffic if work: # # do a work, while GUI will hang for a bit. 会抛出异常。

zmq.DONTWAIT

我希望我可以将它放在while 1: if socket_listen and int(share_state): try: msg = socket_listen.recv_string(zmq.DONTWAIT) except: pass time.sleep(0.01) 内,并且与GUI一起,每次迭代都会检查它。

其他信息:此处轮询相当于:

  • 检查我们是否在socket1上有消息
  • 如果没有那么正常进行
  • 别的什么都可以。

1 个答案:

答案 0 :(得分:1)

  

如何在 while True tkinter 中加入 .mainloop() 不断检查那个插座的状态?

不要使用明确的 while True -loop设计此类部分,更好地使用tkinter - 原生工具:询问 .after() 在不迟于一定时间内重新提交电话(让其他事情同时发生,但具有合理的确定性,您所请求的电话仍将在不迟于""指定的毫秒数。)

我喜欢Tkinter共存事件处理的架构

因此,如果保持有限状态 - 自动机(游戏或GUI前端)在Tkinter - 地面上清晰地制作,则可以享受提供协调的ZeroMQ消息数据"后面"现场,正好是Tkinter - 本机工具,所以不需要任何命令式代码。如果您需要确实具有智能工作的GUI集成,只需将消息转换为 tkinter - 监控变量。

aScheduledTaskID = aGuiRelatedOBJECT.after( msecs_to_wait,
                                            aFunc_to_call = None,
                                            *args
                                            )
# -> <_ID_#_>
# ... guarantees a given wait-time + just a one, soloist-call
#     after a delay of at least delay_ms milliseconds.
#     There is no upper limit to how long it will actually take, but
#     your callback-FUN will be called NO SOONER than you requested,
#     and it will be called only once.
#     aFunc_to_call() may "renew" with .after()
#
# .after_cancel( aScheduledTaskID )  # <- <id> CANCELLED from SCHEDULER
#
# .after_idle() ~ SCHEDULE A TASK TO BE CALLED UPON .mainloop() TURNED-IDLE
#
#     aScheduledTaskOnIdleID = aGuiOBJECT.after_idle( aFunc_to_call = None,
#                                                     *args
#                                                     )
# -> <_ID_#_>

以智能方式使用可立即重用的 tkinter 原生基础架构调度工具非常酷,不是吗?

尾声:

  

阻止来电?最好永远不要使用阻止来电。有人曾说过阻止来电吗? :o)

  

while True ,或阻止 socket.recv() tkinter {{1} }

好吧,可以将这样的循环放入与 .mainloop() 本机基础架构调度程序对齐的组件中,但这个想法实际上是一个反模式,可以将事情变成破坏性的破坏(不仅仅是对于tkinter,一般来说,在任何事件循环处理程序中,期望任何竞争性事件处理程序循环以某种方式容忍或表现为和平的相邻意图的共存是有点冒险的 - 会出现问题(无论是直接阻塞还是因为在调度资源或其他类型的战争时间和资源方面存在过多的主导)。