Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何避免Qt app.exec()阻塞主线程_C++_Multithreading_Qt - Fatal编程技术网

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

C++ 如何避免Qt app.exec()阻塞主线程,c++,multithreading,qt,C++,Multithreading,Qt,我不熟悉Qt,但需要解决一个难题 我创建了一个非常简单的GUI,我需要添加到现有的C++应用程序中。问题是,我只编写了一个模块,插入到一个更大的体系结构中,这个体系结构限制了我对主线程的访问 我的代码必须位于以下四个函数中: 在主线程中运行的Init()函数。 以及在工作线程中运行的WorkerStart()、WorkerStep()和WorkerStop()函数 我在Init()函数中编码了QApplication和GUI对象。但是,当然,在函数末尾调用app.exec()会阻塞代码的其余部分

我不熟悉Qt,但需要解决一个难题

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

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

我在Init()函数中编码了QApplication和GUI对象。但是,当然,在函数末尾调用app.exec()会阻塞代码的其余部分。不可行

我读到的所有东西都说QtGUI对象只能在主线程中运行

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

我发现:

这些解决方案给了我一些不同的行为。方向正确,但不稳定或功能不全。但我不明白,如果QtGUI只能在主线程中运行,而这些解决方案将它们放在其他线程中,为什么这些都是解决方案。因此,这就在其他线程中可以运行什么和不能运行什么的问题上发送了混合消息,这就变得非常混乱

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

非常感谢。 Phil

大多数时候,“主线程”==“GUI线程”,因此人们可以互换使用这些术语——即使是官方文档也会这样做。我同意这是令人困惑的,因为它们不必是相同的。^实际规则是:

GUI类只能从实例化
QApplication
/
QGuiApplication

有了像您这样的插件,您需要做以下几点:

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



    ^注意:Mac OS X上的情况不同。由于Cocoa框架中的限制,主线程必须是GUI线程。我上面概述的步骤可以在Windows/Linux上使用,但不能在Mac上使用。对于Mac,您需要将代码注入主线程——请参阅下面的Kuba Ober评论。

    一个好的解决方案是:git@github.com:midjji/conventive_multi-threaded_qt_gui.git

    那么它只是一个例子

    run_in_gui_thread(new RunEventImpl([](){
            QMainWindow* window=new QMainWindow();
            window->show();
        }));
    
    可在任何时间从任何线程调用,同时负责在bg中为您设置内容


    注意,这还负责创建QApplication并在线程中执行它。但是,如果您已经在某个地方这样做了,它也会起作用。

    QObject::moveToThread
    ,但是您肯定在与这个流作斗争。嗨,Matt。谢谢你的评论。你能为我详细说明一下吗?涉及到许多对象(QApp、QDialog等)和一些线程。那么你是说应该搬到哪里去?将所有内容移动到我的工作线程?还是从main启动的新QThread?或者将QApp留在main中,并将其他内容移动到新线程?如果这真的不适合Qt,有人能推荐一个没有这个限制的不同gui工具包吗?谢谢。这对理解主要内容非常有帮助=gui线程问题。因此,我可以创建一个专用的单独Qt线程。不幸的是,在我的体系结构中还有其他插件也使用Qt(特别是OpenCV Qt),当调用这两个插件时,似乎会发生冲突/阻塞。所以我还没有走出困境。我将尝试运行一个qt事件循环,它会间歇性地自我阻塞自己的线程。希望这能让另一个qt插件玩得更好(时间分割这两个插件)。所以,谢谢你让我通过了第一关。干杯。在OSX上,将代码注入主线程相当简单:
    dispatch\u sync(dispatch\u get\u main\u queue(),^{/*do stuff*/})您也可以在该线程中运行Qt的事件循环,因为它运行本机事件循环。@JKSH它不会阻止调用者,但会“阻止”GUI线程。但由于它将在GUI线程上旋转本机事件循环,因此这可能无关紧要。@JeffTrull Qt实际上不知道哪个线程是“真正的”主线程;Qt只记得使用QObject的第一个线程。因此,如果您确保QApplication是在您的程序中实例化的第一个Qt类,那么无论您在哪个线程中,都不会看到该警告。(换句话说:在创建QApplication之前不要使用任何Qt类。甚至不要调用任何Qt静态方法!)我要补充的是,对于将来遇到这个问题的任何人,如果你使用PyQt,仅仅是执行“导入”的过程就可能触发这个问题。解决方法:甚至在GUI线程中进行导入-避免构建QObject是不够的。