由于 QCoreApplication 事件循环,QThread 永远不会退出

2024-04-28

Problem

所以我有一个 CommandRetriever 类来保存一些命令,并且should在不同的线程上执行这些命令。

class CommandRetriever
{
    public:
        CommandRetriever();
        ~CommandRetriever();
    
        void addCommand( QString, Command* );
        void executeCommands();

    private:
        QMap<QString, Command*> m_commands;
};

addCommand将添加一个新条目m_commands。然而,这是有问题的函数。

void CommandRetriever::executeCommands()
{
    for( auto iter : m_commands.keys() )
    {
        Command *cmd = m_commands.value( iter ); 
         
        // Command, password //
        RemoteConnection *rcon = new RemoteConnection( cmd, "" );

        QThread *thread = new QThread();
        rcon->moveToThread( thread );
        QObject::connect( thread, SIGNAL( started() ), rcon, SLOT( doAsync() ) );
        QObject::connect( rcon, SIGNAL( finished() ), thread, SLOT( quit() ) );
        QObject::connect( rcon, SIGNAL( finished() ), rcon, SLOT( deleteLater() ) );
        QObject::connect( thread, SIGNAL( finished() ), thread, SLOT( deleteLater() ) );
        thread->start();
    }
}

RemoteConnection是我的工作线程。这doAsync()slot 就是处理需要处理的内容。

由于某种原因,我的doAsync()为我的功能rcon对象将被调用,但线程永远不会退出...我的主类如下所示:

int main( int argc, char *argv[] )
{           
    QCoreApplication app( argc, argv );     
    CommandRetriever cr( addr, port );

    //cr.addCommand() ...

    cr.executeCommands();

    return app.exec();
}

我的工人反对(rcon)将输出他们应该输出的内容。然而,即使我的工作对象发出finished()信号,线程仍然存在,并且我的应用程序永远不会完成。我之前连接过这样的信号:

QObject::connect( rcon, SIGNAL( finished() ), thread, SLOT( deleteLater() ) );

但后来我得到了错误:QThread: Destroyed while thread is still running和段错误。

我最近发布了一个与我的线程相关的问题,解决方案是调用thread->wait(),但是,我发现如果我有一个事件循环,thread->wait()不需要,也不是合适的解决方案。使用当前代码,我没有收到任何错误,但我的应用程序会永远运行。我猜app.exec()事件循环无限运行,如果我是对的,我怎样才能正确关闭一切?


Solution

正如暴徒所说:

您需要告诉 QCoreApplication 退出,否则它将永远不会从 exec 函数返回。

这可以通过连接我的工作对象来轻松实现finished()让我的应用程序退出的信号:

QObject::connect( rcon, SIGNAL( finished() ), app, SLOT( quit() ) );

然而,如果我有一个窗口或其他一些 GUI 元素,这样我就能够明确地知道何时需要关闭程序(例如,用户关闭主窗口),这更有意义。

因为我正在运行多个线程,并且因为我的应用程序只是一个控制台应用程序,所以连接我的线程是没有意义的finished()向我发出信号QCoreApplication's quit()投币口。所以我最终使用的是QThreadPool:

void CommandRetriever::executeCommands()
{
     // Quick iterate through the command map //
    for( auto iter : m_commands.keys() )
    {     
        Command *cmd = m_commands.value( iter ); 

         // Command, password; start a new thread for a remote connection. //
        RemoteConnection *rcon = new RemoteConnection( cmd, "" );
        QThreadPool::globalInstance()->start( rcon );
    }
}

应该注意的是,RemoteConnection 类扩展了QRunnable.

为了等待线程完成,我调用:

QThreadPool::globalInstance()->waitForDone();

这将阻塞主线程,直到所有线程完成执行,这对我的控制台应用程序更有意义。它还使代码变得更加干净。

我也删除了app.exec()在我的 main.cpp 中,因为我不再需要事件循环QCoreApplication提供。

我学到的是?QThread并不是实现多线程的唯一方法。就我而言,使用更有意义QThreadPool因为我不需要的信号/槽QThread。另外,您不应该使用QCoreApplication事件循环(如果不需要)。大多数控制台应用程序都属于这一类。


Sources

http://doc.qt.io/qt-5/qrunnable.html http://doc.qt.io/qt-5/qrunnable.html

http://doc.qt.io/qt-4.8/qthreadpool.html http://doc.qt.io/qt-4.8/qthreadpool.html


如果你不告诉你的QCoreApplication反对退出,它永远不会离开exec()功能。

您可以致电QCoreApplication::quit()直接插入插槽,或将信号连接到其上。

...
connect(thread, SIGNAL(finished()), qApp, SLOT(quit()));

qApp是一个全局指针,引用唯一的应用程序对象。和打电话是一样的QCoreApplication::instance().

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

由于 QCoreApplication 事件循环,QThread 永远不会退出 的相关文章

随机推荐

  • iOS 不同设备的单一尺寸类别中的不同字体大小

    在iOS 8中 我们可以为每个尺寸类别设计不同的UI布局 我面临的问题是 我设计了紧凑宽度和常规高度的布局 纵向所有 iPhone 的尺寸类别 但我想为 3 5 和 4 英寸设备 iPhone 4 和 5 保留较小的标签字体大小 然后对于
  • IntelliJ IDEA 的 Mylyn 替代品?

    我们公司已经使用 Unfuddle 一年了 我所有的同事都可以使用名为 Mylyn 的 Eclipse 插件轻松访问 Unfuddle 票证 IntelliJ IDEA 是否存在类似的东西 如果没有 你能建议一些替代方法来处理来自 IDEA
  • iPhone 开发——performSelector:withObject:afterDelay 还是 NSTimer?

    重复方法调用 或消息发送 我猜合适的术语是 x秒 是使用 NSTimer NSTimer 的 ScheduledTimerWithTimeInterval target selector userInfo repeats 还是让该方法在最后
  • C++11 中的“类模板Example;”语句是什么意思?

    我已被提及 显式模板实例化 http www cplusplus com articles 1C75fSEw at cplusplus com http www cplusplus com 给出了以下示例 template
  • 如何用好Fortran语句标签?

    我正在开发一个用 Fortran 95 编写的模型 我对此完全陌生 语句标签的概念似乎很奇怪 到目前为止我只找到了标签可以由作者任意决定的解释 通常以 10 为增量 除了更容易地找出语句的结尾位置之外 这些标签还有其他实际用途吗 以及关于如
  • 会话在 Laravel 5.4 上不持久

    我在 Laravel Sessions 方面遇到了一些问题 现在我在 Laravel 5 4 下工作 所以 我使用以下代码来设置会话 request gt session gt put usuario somevalue 但是当我尝试使用以
  • 您必须至少选择一个列出的平台才能显示

    我正在创建一个简单的应用程序 当我尝试保存更改时收到此错误 您必须至少选择一个要显示的列出平台 请参阅此处的屏幕截图 http panstickers com au webimages fb error gif http pansticke
  • Ace编辑器使用javascript触发事件

    有没有类似的东西 editor getSession trigger change 我想要这个的原因是因为编辑器进出新的 所以当它返回视图时我需要它做正常的 更改 事情 但我不想等待用户输入 目前我有 editor getSession o
  • 如何解决curl php中的HTTP/1.1 400 Bad Request

    我必须打一个 aspx来自 php 代码的页面 url 我试图使用curl 来访问 但出现以下错误并且 url 中没有空格 HTTP 1 1 400 Bad Request Content Type text html charset us
  • PHP 通过 FTP 下载整个文件夹(递归)

    我目前有一个非常大的网站 大小约为 5GB 包含 60 000 个文件 当前主机并没有做太多事情来帮助我将网站转移到新主机 我的想法是在新主机上制作一个简单的脚本 通过 FTP 传输到旧主机并下载整个 public html 文件夹 递归地
  • 在进行字符识别之前使用 OpenCV 进行图像预处理(超正方体)

    我正在尝试开发简单的 PC 应用程序用于车牌识别 Java OpenCV Tess4j 图像不是很好 进一步它们会很好 我想对超立方体图像进行预处理 但我被困在车牌检测 矩形检测 上 我的步骤 1 源图像 Mat img new Mat i
  • 在 Matlab、VB6 和 VB.NET 程序之间发送消息的最简单方法

    我们正在将一套数据采集和分析例程从 VB6 程序升级为 VB NET VB6 和 Matlab 程序的混合体 我们希望保持系统模块化 单独的 EXE 以便我们可以轻松创建专门的独立分析程序 而无需不断升级大型应用程序 当所有程序都是用 VB
  • 何时在 Springs @Configuration 中将 proxyBeanMethods 设置为 false?

    当查看 spring 自动配置时源代码 https github com spring projects spring boot tree master spring boot project spring boot autoconfigu
  • 如何用Spring进行只读和读写的数据库路由

    我正在研究 Spring 中的事务路由 但我的应用程序存在运行时问题 我有两个 MySQL 数据库 一个用于读取 一个用于读 写 但是我的路由配置不起作用 当我应用只读配置时 我没有成功 这是我的配置 pom xml
  • Akka、SQS 和 Camel 的消费者投票率

    我正在做的一个项目需要从SQS读取消息 我决定使用Akka来分布式处理这些消息 由于 Camel 支持 SQS 并且在 Consumer 类中内置了 Akka 中使用的功能 因此我认为最好以这种方式实现端点并读取消息 尽管我还没有看到很多人
  • 如何在中等规模的 Rails 应用程序中组织控制器?

    我正在开发一个具有相当多相关模型的应用程序 并且想听听一些关于如何最好地组织控制器的意见 以下是我一直在考虑的一些选择 1 为控制器命名空间 例如 有一个controllers admin 目录和一个controllers public 目
  • Apache mod_rewrite:在 Windows 计算机上使用 PHP 脚本的 RewriteMap 指令

    这已经让我发疯了 我似乎无法让 RewriteMap 指令适用于 Windows 上的 php 脚本 这是我的 httpd conf 文件中的相关片段
  • 在 AspNet WebApi 帮助页面中生成模型描述

    我如何生成一个描述对于 Asp Net Web Api 帮助页面中的我的模型 Example 正如您从示例中看到的 我已经可以生成Name Type and Additional Information 但我如何生成Description
  • 部署后配置文件中缺少

    更新 我在下面有一个问题 但实际上我的问题可以通过提出一个稍微不同的问题来解决 为什么在某些机器上我的应用程序会抛出错误 Configuration system failed to initialize System Configurat
  • 由于 QCoreApplication 事件循环,QThread 永远不会退出

    Problem 所以我有一个 CommandRetriever 类来保存一些命令 并且should在不同的线程上执行这些命令 class CommandRetriever public CommandRetriever CommandRet