【问题标题】:Qt-Signal not connecting in virtual machineQt-Signal未在虚拟机中连接
【发布时间】:2018-04-04 09:54:58
【问题描述】:

我在 RedHat 7.4 上使用 GCC 4.8.5 和 Qt 4.8.5 进行开发和编译。代码必须是静态链接的。然后在运行 Scientific Linux 6.7 版的虚拟机上执行。 memcpy-Wrap 用于防止依赖于较新的 GLIBC >= 2.4

我有以下 MWE:

#include <iostream>
#include <unistd.h>
#include <QtCore>
#include <QThread>

__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");
extern "C" {
void *__wrap_memcpy(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); }
}

class Worker : public QThread {
    void run() {
        std::cout << "WORKER: Started." << std::endl;
        QObject::connect(this, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit()));
        int i=0;
        while(i++<3) {
            std::cout << "WORKER: I am running." << std::endl;
            usleep(1e6);
        }
        std::cout << "WORKER: Finished." << std::endl;
    }
};

int main(int argc, char** argv) {

    std::cout << "MAIN: Init QCoreApplication" << std::endl;
    QCoreApplication qtApplication(argc, argv);

    std::cout << "MAIN: Init Worker" << std::endl;
    Worker myWorker;
    myWorker.start();

    std::cout << "MAIN: Start Event-Loop." << std::endl;
    qtApplication.exec();

    std::cout << "MAIN: Event-Loop finished." << std::endl;
    return 0;
}

这段代码是在 RedHat 系统上编译的

g++ -I$QTD/mkspecs/linux-g++ -I$QTD/include -I$QTD/include/QtCore -o mwe mwe.cpp  -Wl,--wrap=memcpy -L$QTD/lib/ -lQtCore -lQtNetwork -lglib-2.0 -lrt -lpthread -ldl -lz

$QTD 存放我安装的 Qt-4.8.5 的位置。

在 Red-Hat 系统上预期并观察到以下行为:

MAIN: Init QCoreApplication
MAIN: Init Worker
MAIN: Start Event-Loop.
WORKER: Started.
WORKER: I am running.
WORKER: I am running.
WORKER: I am running.
WORKER: Finished.
MAIN: Event-Loop finished.

在 Scientific-Linux-System 上观察到以下行为:

MAIN: Init QCoreApplication
MAIN: Init Worker
MAIN: Start Event-Loop.
WORKER: Started.
WORKER: I am running.
WORKER: I am running.
WORKER: I am running.
WORKER: Finished.

然后应用程序永远不会完成。

似乎在 Red-Hat-System 中,来自工作线程的完成信号连接到核心应用程序中的退出槽。这似乎不会在 Scientific-Linux-System 中发生。有没有人有任何建议为什么会发生这种情况以及如何调试它?

【问题讨论】:

  • 在调试器下运行它以找出它卡在哪里。此外,您可以连接到调用QCoreApplication::quitlambda,而不是连接到QCoreApplication::quit——这将允许您添加一些额外的诊断输出。
  • @G.M.我建议也更喜欢 Qt5 信号和 lambda,但 OP 声明在 Qt 4.8.5 上。 Qt5 信号是否已经可用于此版本?
  • 我认为你们俩都在谈论新签名,我不必将大写字母“SIGNAL”和“SLOT”放入,而只需提供类的方法名称?是的,我也明白这只是从 Qt5 开始,但在我的版本中不可用。
  • @Scheff 抱歉,我错过了Qt4 约束。这排除了lambda,但调用QCoreApplication::quit 的函数将起到相同的作用。
  • 您是否尝试过手动调用退出槽,而在您的有价值线程末尾没有连接?使用 QMetaObject::invokeMethod 它应该在线程边界上工作相同

标签: c++ qt signals slots


【解决方案1】:

你必须以正确的方式使用 QThread。 重载 run() 函数是不安全的,Nokia 之前接受过它并展示了如何使用 QThread。

Look at this documentation.

【讨论】:

【解决方案2】:

如前所述 - 不推荐在 Qt 中使用线程。但这对你的情况很好。无论如何,我建议您尝试下一种方法:

class Worker : public QThread {
    Q_OBJECT // Don't forget this macro
    void run() {
        std::cout << "WORKER: Started." << std::endl;
        // QObject::connect(this, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit()));
        int i=0;
        while(i++<3) {
            std::cout << "WORKER: I am running." << std::endl;
            usleep(1e6);
        }
        std::cout << "WORKER: Finished." << std::endl;
        this->deleteLater();
    }
};

int main(int argc, char** argv) {

    std::cout << "MAIN: Init QCoreApplication" << std::endl;
    QCoreApplication qtApplication(argc, argv);

    std::cout << "MAIN: Init Worker" << std::endl;
    Worker *myWorker = new Worker();
    QObject::connect( myWorker, SIGNAL(destroyed()), &qtApplication, SLOT(quit());
    myWorker->start();

    std::cout << "MAIN: Start Event-Loop." << std::endl;
    qtApplication.exec();

    std::cout << "MAIN: Event-Loop finished." << std::endl;
    return 0;
}

【讨论】:

  • 我想,当我在派生类中声明信号/插槽时,我只需要 Q_OBJECT 吗? Worker 类只重载了 run() 方法,所以它应该不需要宏,对吧?
  • 它在 SL 系统上显示与以前相同的行为。
  • 不知道...顺便说一句,在主函数中尝试这样的事情:QTimer::singleShot(100, &amp;app, SLOT(quit())); - 它有效吗?
  • 我在主线程中使用了QTimer::singleShot(1e4, &amp;qtApplication, SLOT(quit()));。然后工作人员在大约 3 秒内完成,应用程序在 10 秒后自行退出。所以 qtApplication 的事件循环确实是活跃的,并且可以通过自己线程的信号来监听和到达。
  • @Tobias 你能在Worker 类中添加一个槽,并将它与它自己的finished 信号连接起来,只是为了测试信号是否被发出(在槽内放一个qDebug &lt;&lt; "..." )。
猜你喜欢
  • 1970-01-01
  • 2018-03-28
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多