【发布时间】:2011-08-18 21:34:24
【问题描述】:
我想在 Qt 中从我用 QtConcurrent::run 调用的函数发出信号
这可能吗?似乎我的插槽永远不会被调用。所有的信号、槽和函数都是同一个类对象的一部分。我尝试在主线程和从线程中建立连接。我真的不在乎信号和槽是否在同一个线程中,我只想让它发生。
谢谢
【问题讨论】:
标签: c++ multithreading qt
我想在 Qt 中从我用 QtConcurrent::run 调用的函数发出信号
这可能吗?似乎我的插槽永远不会被调用。所有的信号、槽和函数都是同一个类对象的一部分。我尝试在主线程和从线程中建立连接。我真的不在乎信号和槽是否在同一个线程中,我只想让它发生。
谢谢
【问题讨论】:
标签: c++ multithreading qt
以下在 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 中,您不需要帮助类来证明它可以工作:
#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 也会做同样的事情,并将信号添加到接收对象线程的事件队列中。
如果接收线程被阻塞,因此永远不会重新进入事件队列,则接收对象的槽无法接收到信号。
【讨论】:
QThread::currentThread) 和 target 线程 (@987654325) 之间完成@)。 发送对象的线程在该决定中没有任何意义。
你真的应该在 QtConcurrent::run() 中使用 QFuture 和 QFutureWatcher。
【讨论】:
是的,这是可能的。 看看小例子:
在这个例子中,我们要实现多线程。 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;
}
【讨论】: