QtConcurrent::运行发出信号

QtConcurrent::run emit signal

本文关键字:信号 运行 QtConcurrent      更新时间:2023-10-16

我想在Qt中发出一个信号,从我用QtConcurrent调用的函数::run

这可能吗?我的位置好像从来没被叫过。所有的信号、槽和函数都是同一个类对象的一部分。我已经尝试在主线程和从线程中进行连接。我真的不关心信号和插槽是否在同一个线程中,我只是想让它发生。

谢谢

下面的代码在Qt 4.8.7中运行良好。信号从工作线程发出,并在主线程中消耗。我们断言槽在主线程中运行,函子在工作线程中运行。

// https://github.com/KubaO/stackoverflown/tree/master/questions/concurrent-emit-qt4-7114421
#include <QtCore>
class Helper : public QObject {
   Q_OBJECT
public:
   int n = 0;
   Q_SLOT void increment() {
      Q_ASSERT(QThread::currentThread() == qApp->thread());
      n++;
   }
};
int main(int argc, char **argv)
{
   QCoreApplication app(argc, argv);
   Helper helper;
   Q_ASSERT(helper.n == 0);
   QtConcurrent::run([&]{
      Q_ASSERT(QThread::currentThread() != qApp->thread());
      QObject src;
      QObject::connect(&src, SIGNAL(destroyed(QObject*)), &helper, SLOT(increment()));
      QObject::connect(&src, SIGNAL(destroyed(QObject*)), &app, SLOT(quit()));
   });
   app.exec();
   Q_ASSERT(helper.n == 1);
}
#include "main.moc"

在Qt 5中,您不需要helper类来演示它的工作:

#include <QtConcurrent>
int main(int argc, char **argv)
{
   QCoreApplication app(argc, argv);
   int n = 0;
   Q_ASSERT(n == 0);
   QtConcurrent::run([&]{
      Q_ASSERT(QThread::currentThread() != qApp->thread());
      QObject src;
      QObject::connect(&src, &QObject::destroyed, &app, [&]{
         Q_ASSERT(QThread::currentThread() == qApp->thread());
         n ++;
         qApp->quit();
      });
   });
   app.exec();
   Q_ASSERT(n == 1);
}

您可以为该连接使用Qt::QueuedConnection(将其传递给建立连接的connect调用),因为信号将始终从与接收器对象线程不同的线程发出。

Qt::AutoConnection也会做同样的事情,并将信号添加到接收对象的线程的事件队列中。

如果接收线程被阻塞,因此永远不会重新进入事件队列,则信号无法被接收对象的插槽接收。

你真的应该使用QFuture和QFutureWatcher与QtConcurrent::run()。

是有可能的。看一个小例子:

在这个例子中,我们想要实现多线程。longProcess函数进入线程池并在线程池中进行处理,然后返回到主线程

Test.h

Class Test: public QObject
{
    Q_OBJECT
public:
    explicit Test(QObject *parent = nullptr);
    void resultAvailable();
    static void doLongProcess(Test *test);
signals:
    void finishedProcess(const QString &massage);
public slots:
    void captureSignal(const QString &message);
};

Test.cpp

void Test::resultAvailable()
{
        QtConcurrent::run(&ContactsModelManager::doLongProcess, this);
        connect(this , &Test::finishedProcess,
                this , &Test::captureSignal);
}
//attention!! doLongProcess is static fnuction
void Test::doLongProcess(Test *test)
{
    //this process is very long
    test->longProcess();
}
 void Test::longProcess()
{
    //do your process
    //at the end emit your signal 
    emit finishedProcess("finished process in another thread");
}
void Test::captureSignal(const QString &message)
{
   Qdebug() << "message is: " << message;
}