[Solved][Qt concurrent] Emit signal from run method do not work
-
Hi Guys,
I have test() function which is executed using QtConcurrent::run method in different thread. My main thread is GUI thread. When any signal is emmited from test() function, main thread does not catch that so i tried to execute slot OnTestSignal() which executes in main thread and emit signal from there. still the signal is not emmited.
@#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QtConcurrentRun>
#include <QCoreApplication>
#include <QTimer>MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);// Run test in different thread
QtConcurrent::run((*this),&MainWindow::test);
QObject::connect(this,SIGNAL(testSignal(int)),ui->progressBar,SLOT(setValue(int)),Qt::QueuedConnection); /** * This signal is emmited and progress bar changes */ emit testSignal(qrand()0);
}
MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::test()
{
qDebug() << "start :" << QThread::currentThread() ->signalsBlocked()<< " : " << thread()->signalsBlocked();
qDebug() << "Thread : " << QThread::currentThread() << " : " << thread();int i; int j; while(1) { ++i; if(i > 10) { i =0; QMetaObject::invokeMethod(this,"onTestSignal",Qt::QueuedConnection); //emit testSignal(); /* DOES NOT WORK */ } }
}
void MainWindow::onTestSignal()
{
// Verify that test executed in different thread and this funtion is executed in main threadqDebug() << "onTestSignal() : " << QThread::currentThread() << " :Main Thread : " << thread(); /** * Executed in main thread still signal is not been emmited, WHY ???? */ emit testSignal(qrand()0); // Did not work QCoreApplication::processEvents();
}
@What am i doing wrong here ? i should be getting a signal but that not happening
-
As i understand QMetaObject::invokeMethod() doesn't work either.
Slot connected to a signal with Qt::QueuedConnection is invoked only when execution goes back to an event loop. And your while(1) construction prevents event loop from being entered. That is, events for onTestSignal are just queued without possibility for execution. -
QMetaObject::InvokeMethod() method works here, and onTestSignal() function is also get called (Which executed in main thread ). it also prints the thread information. However it does not emit signal.
-
Does connect(...) succeed? emit testSignal() should emit at least one int parameter.
In addition, you should connect() before running your method. If your thread gets scheduled immediately you will miss all signals emitted before execution returns to your main thread.
[quote author="p-himik" date="1322111612"]As i understand QMetaObject::invokeMethod() doesn't work either. Slot connected to a signal with Qt::QueuedConnection is invoked only when execution goes back to an event loop. And your while(1) construction prevents event loop from being entered. That is, events for onTestSignal are just queued without possibility for execution.[/quote]
You'll need a running event loop in the receiving thread, which is not the one executing while(1).
-
For this example it is fine to miss few signals.
Could you please suggest, how to run even loop in the above example ?
-
I understood what i was doing wrong here.
For same issues please refer
"http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects":http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects
-
An event loop is started by calling exec(), for example QCoreApplication::exec(). Pending events can be processed (once) using processEvents().
@
class SignalTest : public QObject
{
Q_OBJECTpublic:
void test()
{
qDebug() << Q_FUNC_INFO << QThread::currentThread() << thread();emit signal(0); }
signals:
void signal(int parameter);public slots:
void slot(int parameter)
{
Q_UNUSED(parameter);qDebug() << Q_FUNC_INFO << QThread::currentThread() << thread(); }
};
int main(int argc, char *argv[])
{
QCoreApplication application(argc, argv);qDebug() << Q_FUNC_INFO << QThread::currentThread(); SignalTest signalTest; signalTest.connect(&signalTest, SIGNAL(signal(int)), &signalTest, SLOT(slot(int)), Qt::QueuedConnection); QtConcurrent::run(&signalTest, &SignalTest::test); return application.exec(); // run event loop for main thread
}
@[quote author="vishwajeet" date="1322117812"]For this example it is fine to miss few signals.[/quote]
Just make sure you are aware of it. Another pitfall is the following restriction of QtConcurrent::run():
[quote]Note that the QFuture returned by QtConcurrent::run() does not support canceling, pausing, or progress reporting. The QFuture returned can only be used to query for the running/finished status and the return value of the function.[/quote]
This means, that if your method never returns (as in your case, while(1) { ... }) you will have to provide a mechanism to break, otherwise you won't be able to terminate the thread.