我想從QtConcurrent :: runQtConcurrent ::運行發射信號
這個函數中發出一個Qt信號這可能嗎?好像我的插槽永遠不會被調用。所有的信號,插槽和函數都是同一個類對象的一部分。我試圖在主線程和從線程中建立連接。我真的不在乎信號和插槽是否在同一個線程中,我只是想讓它發生。
由於
我想從QtConcurrent :: runQtConcurrent ::運行發射信號
這個函數中發出一個Qt信號這可能嗎?好像我的插槽永遠不會被調用。所有的信號,插槽和函數都是同一個類對象的一部分。我試圖在主線程和從線程中建立連接。我真的不在乎信號和插槽是否在同一個線程中,我只是想讓它發生。
由於
可以使用Qt::QueuedConnection
用於該連接(將它傳遞給connect
呼叫該建立連接),由於信號將總是從比所述接收器對象的線程不同的線程發出的。
的Qt::AutoConnection
也會做同樣的事情,並且信號添加到接收對象的線程的事件隊列。
如果接收線程被阻塞,因而從未重新進入事件隊列,信號不能被接收對象的時隙中接收。
你真的應該使用QFuture和QFutureWatcher與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,你不需要輔助類來證明它的工作原理:
#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);
}
這是不正確的:默認的自動連接將做的工作就好了。 –
@KubaOber:你錯了。 OP表示所有插槽和信號都屬於一個對象。因此,AutoConnection將評估爲DirectConnection。這可能不是OP想要的,因爲這要求槽以線程安全的方式使用對象。這種同步必須在這種情況下手動完成。 QueuedConnection將消除手動同步的需要,因爲該槽將在對象所在的線程中調用。 Qt將處理實現該操作所需的同步。 – smerlin
發件人的對象無關緊要。發送和接收線程之間的比較是在信號被髮射的時間完成的,並且在當前* *線程('的QThread :: currentThread')和* *目標線程('接收機 - >螺紋()')之間進行。 *發送對象的*線程在該確定中沒有任何形式。 –