You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让GTK界面与asyncio协同工作,避免GUI冻结?

解决GTK3与asyncio协同运行避免GUI冻结的方案

你的代码核心问题是每次点击按钮调用asyncio.run()会启动独立的asyncio事件循环,阻塞了GTK的主循环,导致GUI冻结。要实现GTK和asyncio的无缝兼容,需要让两个事件循环协同运行,而不是各自独立执行。

最优实现思路

GTK基于GLib主循环,我们可以将asyncio的事件循环整合到GLib主循环中,让两者共享同一个线程的事件调度,这样异步任务执行时,GTK仍能响应UI操作,不会出现冻结。

修正后的完整代码

import asyncio
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib


async def simulate_get_results():
    await asyncio.sleep(5)
    return ['Imagine these are results from an API']


class Window(Gtk.Window):
    def __init__(self):
        super().__init__()
        self.search_button = Gtk.Button(label='Press me')
        # 绑定按钮点击回调
        self.search_button.connect('clicked', self.on_button_clicked)
        self.add(self.search_button)

    def on_button_clicked(self, button: Gtk.Button):
        # 将异步任务加入asyncio事件循环,不阻塞GTK主循环
        asyncio.create_task(self.update_button_label(button))

    async def update_button_label(self, button: Gtk.Button):
        results = await simulate_get_results()
        # 直接更新UI,事件循环整合后天然在主线程,无需额外同步
        button.set_label(results[0])


async def main():
    win = Window()
    win.connect('destroy', Gtk.main_quit)
    win.show_all()

    # 获取asyncio事件循环
    loop = asyncio.get_event_loop()
    # 将asyncio事件循环整合进GLib主循环,实现协同调度
    def run_asyncio_iteration(source, condition):
        loop.call_soon(loop.stop)
        loop.run_forever()
        return True

    GLib.io_add_watch(loop._selector._fd, GLib.PRIORITY_DEFAULT, run_asyncio_iteration)

    # 启动GTK主循环
    Gtk.main()


if __name__ == '__main__':
    asyncio.run(main())

关键细节说明

  • 事件循环整合:通过GLib.io_add_watch监听asyncio事件循环的文件描述符,每当asyncio有事件需要处理时,GLib主循环会调度执行asyncio的事件迭代,确保两个循环都能正常响应事件。
  • 异步任务调度:按钮回调中用asyncio.create_task()将异步任务加入事件循环,不会阻塞当前GTK主循环的执行。
  • UI线程安全:所有操作都在同一个主线程的事件循环中,GTK的UI更新操作天然线程安全,完美支持高频通信场景(比如搜索框实时输入)。

内容的提问来源于stack exchange,提问作者Grass Lunatic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 11:43:13