如何避免Qt app.exec()阻塞主线程

时间:2014-03-09 23:03:42

标签: c++ multithreading qt

我是Qt的新手,但需要解决一个棘手的问题。

我创建了一个非常简单的GUI,我需要将其添加到现有的C ++应用程序中。问题是,我只编写了一个插入更大架构的模块,这限制了我对主线程的访问。

我的代码必须位于以下四个函数中: 一个Init()函数,它在主线程中运行。 和在工作线程中运行的WorkerStart(),WorkerStep()和WorkerStop()函数。

我在Init()函数中编写了我的QApplication和GUI对象。但是,当然,在该函数末尾调用app.exec()会阻止整个代码。不可行。

我正在阅读的所有内容都说Qt gui对象只能在主线程中运行。

所以我的问题是,如何在init()函数(主线程)中设置我的gui并允许它从那时起仅使用工作线程运行?

我发现了这个:QApplication In Non-Main Thread

这些解决方案给了我一些不同的行为。在正确的方向,但不稳定或完全功能。但我不明白为什么这些解决方案根本不存在qt gui只能在主线程中运行,而这些解决方案将它们放在其他线程中。所以那就是在其他线程中可以运行和不运行的内容上发送混合消息,这会变得非常混乱。

似乎在现有的C ++程序中添加gui而不将其锁定在exec()函数中应该是一个相当常见的情况,所以我觉得我错过了一些明显的东西。有人可以帮我解决这个问题吗?

提前非常感谢。 菲尔

2 个答案:

答案 0 :(得分:21)

大多数时候,“主线程”==“GUI线程”,所以人们可以互换地使用这些术语 - 甚至官方文档都这样做。我同意这很令人困惑,因为它们不一定是相同的。^实际的规则是:

  

只能从实例化QApplication / QGuiApplication

的线程访问GUI类

使用像你这样的插件,这是你需要做的:

  1. 创建新的std::thread(不是QThread
  2. 在该线程中运行init函数。让它实例化您的QApplication / QGuiApplication并启动事件循环
  3. 确保仅从该线程访问所有GUI对象。
  4. Voila,你现在有一个不是你主线的GUI线程。


    ^ 注意:在Mac OS X上有一个不同的故事。由于Cocoa框架的限制,主线程必须是GUI线程。我上面概述的步骤适用于Windows / Linux,但不适用于Mac。对于Mac,您需要将代码注入主线程 - 请参阅下面的Kuba Ober的评论。

答案 1 :(得分:0)

一个好的解决方案位于:git@github.com:midjji / convenient_multithreaded_qt_gui.git

那只是例如

run_in_gui_thread(new RunEventImpl([](){
        QMainWindow* window=new QMainWindow();
        window->show();
    }));

随时可以在任何线程中调用,同时还要在bg中为您进行设置。

注意,这还需要创建一个QApplication并在线程中执行它。但如果您已经在某个地方这样做了,也可以使用。