【发布时间】:2015-04-21 20:22:24
【问题描述】:
我正在使用 asyncio 和 tkinter 开发一个简单的图形网络应用程序。我遇到了将异步事件循环与 Tk 的主循环结合起来的问题。如果可能的话,我想在没有线程的情况下这样做,因为这两个库(尤其是 tkinter)都不是线程安全的。目前,我在 asyncio 协程中使用 Tk.update,它只运行 tk 事件循环的单次迭代:
@asyncio.coroutine
def run_tk(tk, interval=0.1):
try:
while True:
tk.update()
yield from asyncio.sleep(interval)
except TclError as e:
if "application has been destroyed" not in e.args[0]:
raise
但是,为了探索所有选项,我想知道是否可以反过来——是否可以在 tk 回调中仅调用异步事件循环的单次迭代。
【问题讨论】:
-
你可以combine the Tk main loop with asyncio,但我不知道这是否仍然允许你处理网络流量(即网络事件如何流入Tk主循环)?
-
它似乎可以工作,但它作弊 - 它创建了一个 TkEventLoop,它基本上在循环中运行
update,但也创建了一个传统的事件循环来执行网络 i/o 并运行它在一个线程中。这是两全其美的;唯一的好处是直接回调(loop.call_later)在 Tk 事件循环中直接调用。 -
我在问题和答案中遗漏了一个最小的工作示例。
-
接受的答案显示了如何运行事件循环的单个步骤。您应该能够在 tkinter 主循环中反复调用
run_once以“运行”asyncio。 -
有
loop._run_once()。但是,如果您在另一个线程上运行 asyncio 循环时坚持使用它自己的线程,则没有问题。大多数 asyncio 也不是线程安全的。您可以分别使用loop.run_coroutine_threadsafe()和loop.call_soon_threadsafe()从 tkinter 线程调度协程和回调。
标签: python events tkinter tk python-asyncio