GTK+ 接口应该在单独的线程中运行吗?
Posted
技术标签:
【中文标题】GTK+ 接口应该在单独的线程中运行吗?【英文标题】:Should GTK+ interface run in a separate thread? 【发布时间】:2014-03-19 15:40:09 【问题描述】:我正在 GTK+ 中迈出第一步(C++
和 gtkmm
更具体),我对如何最好地构建我的程序有一个相当概念性的疑问。现在我只希望我的 GUI 通过打印几个值来显示我的 C++ 程序中发生的事情,并且由于我的主线程在 GUI 窗口运行时停止,所以我遇到了将处理/计算操作和单独线程中的图形界面。这是否被普遍认为是最好的方法,根本不重要,甚至不相关?
【问题讨论】:
如果你从不做任何花费超过几秒钟的事情,而且通常是亚秒级的,那么不要使用单独的线程。 OTOH,如果您有长时间运行的操作,请在单独的线程中生成这些操作并将进度消息发布到主线程。但是将 GUI 线程视为主线程 - 其他线程是 WORKER 线程。 GUI 处于控制之中。 【参考方案1】:除非你有充分的理由,否则最好不要创建新线程。同步很难做到正确。
GUI 编程是事件驱动的(点击一个按钮就会发生一些事情)。因此,您可能需要将后台处理与 GUI 事件系统联系起来。
如果您的后台处理需要很长时间,您需要将其分成多个快速块。在每个块结束时,您可以更新进度条并安排下一个块。
这意味着您可能需要使用一些状态机模式。
还要确保任何 IO 都是非阻塞的。
【讨论】:
...所有这些对于任何非平凡的接口都很难正确处理,因此糟糕的接口无处不在。 您可以在适当的时候使用“DoEvents”即gtk_main_iteration()
来避免状态机模式。取消按钮应该只设置一个取消标志,然后在 DoEvents 之后检查它。不要忘记禁用 GUI(进度对话框/取消按钮除外),以便用户无法开始重叠任务。
@Ben 如何只运行一次主循环?我正在使用Gtk::Application->run(Gtk::Window)
并且在文档中找不到任何内容。显然iteration()
是Gtk::Main
的成员。
如果你有任何长时间运行的东西,你必须时不时地让步,否则你最终会得到所说的糟糕的用户界面【参考方案2】:
这是一个使用主循环将冗长操作拆分为较小块的示例,无需额外线程。 Lazy Loading using the main loop.
【讨论】:
【参考方案3】:是的,绝对!(回应你的标题)
GUI必须在单独的线程中运行。如果您曾经遇到过那些在操作进行时锁定的非常烦人的界面1,那么您就会知道为什么无论操作发生什么都要始终运行 GUI 非常重要。
这是一个用户体验。
1我不是指在操作过程中禁用某些按钮的那些(这是正常的),而是那些似乎一切都冻结的那些。
【讨论】:
这与线程无关。线程只是这个问题的一种解决方案,而不是解决方案。【参考方案4】:这是相反的:主线程应该是Gtk的,而长时间的处理/计算任务应该在线程中完成。
文档给出了一个明确的例子: https://pygobject.readthedocs.io/en/latest/guide/threading.html
【讨论】:
以上是关于GTK+ 接口应该在单独的线程中运行吗?的主要内容,如果未能解决你的问题,请参考以下文章
当我运行多个与 CPU 核心/线程数匹配的线程时,每个线程会在单独的核心/线程上运行吗?