PDA

View Full Version : invokeMethod doesn't change the thread



lamb
13th July 2014, 20:41
Hi,
I try to call invokeMethod or send a signal in a typical worker (=QObject) and QThread scenario. But the invokeMethod doesn't change from the worker's thread into the main thread. And the signal has the same problem. My code is as follows:

Worker::Worker(Ui::MainWindow *ui, QObject *parent) :
QObject(parent)
{
m_ui = ui;
m_ui->statusBar->showMessage("Worker started.");
connect(this, SIGNAL(sigWriteSomethingInTheGui()), this, SLOT(slotWriteSomethingInTheGui()), Qt::QueuedConnection);
}

void Worker::slotDoSomeWork()
{
m_ui->statusBar->showMessage("slotDoSomeWork started.");

bool ret = QMetaObject::invokeMethod(this, "slotWriteSomethingInTheGui", Qt::QueuedConnection); //We try to change from worker thread into the main thread.

emit sigWriteSomethingInTheGui(); //Here we try to do the same...
}

void Worker::slotWriteSomethingInTheGui()
{
m_ui->statusBar->showMessage("slotWriteSomethingInTheGui started."); //If this slot is called we should be in the main thread after calling
//invokeMethod(this, "slotWriteSomethingInTheGui", Qt::QueuedConnection);
}



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

m_pWorker = std::unique_ptr<Worker>( new Worker(ui));

m_pWorker->moveToThread(&m_WorkerThread);

connect(&m_WorkerThread, SIGNAL(started()), m_pWorker.get(), SLOT(slotDoSomeWork()));
connect(m_pWorker.get(), SIGNAL(sigWriteSomethingInTheGui()), this, SLOT(slotWriteIt()));

m_WorkerThread.start();
}

MainWindow::~MainWindow()
{
delete ui;

m_WorkerThread.quit();
m_WorkerThread.wait(2000);
}

void MainWindow::slotWriteIt()
{
ui->statusBar->showMessage("Yes!"); //Yes. We are in the main thread.
}


Can someone explain this behaviour?

Thanks,

The Lamb

anda_skoa
14th July 2014, 08:47
Your Worker object was moved into the worker thread, its slot.
Slots, when invoked through Qt:QueuedConnection will be executed in the context of the object's owner thread.
In your case the worker thread.

Connect the signal to some object belonging to the main thread, or invoke a slot of such an object. That's why it works for MainWindow::slotWriteIt()

Btw, your slotDoSomeWork(), which is supposed to run in the worker thread, access UI directly. This is bad. Only the main thread is allowed to work with UI objects.

Cheers,
_

lamb
14th July 2014, 09:53
Thanks,
now I understand the moveToThread method more in details. The whole object (Worker object) lives in this thread. Even if the connect

connect(this, SIGNAL(sigWriteSomethingInTheGui()), this, SLOT(slotWriteSomethingInTheGui()), Qt::QueuedConnection);
was applied in the main thread. After calling moveToThread there is no chance for the worker class to switch into the main thread by itself.
Greetings,

The Lamb