QThread Proper Use ?? connect Problems....
Hi everyone,
I'm new on this forum. I'm using Qt4.8.6 for its GUI performances but now I want to use QThreads properly. I saw on the web different ways to declare and use them.
- redefinition of methods run() of Object inheriting of QThread class => Wrong way
- definition of a Worker and worker->moveToThread (QThread*) => Right way ??? (https://forum.qt.io/topic/14378/my-t...y-use-qthreads)
I developed a small project with these two methods to compare them. threadA which displays "A" and threadB which displays "B". To start/stop each threads, there are buttons. Both of these methods work (displaying AAAAA when AButton pushed, BBBBBBB when BButton pushed and ABABABABABA when both are pushed...
BUT if I follow steps of the second method (Correct use), I must connect :
Code:
connect(thread, SIGNAL(started()), worker, SLOT(process())); OK
connect(worker, SIGNAL(finished()), thread, SLOT(quit())); OK
but when I add these two connections, I have : Violation of Ox0FFFFFFFF emplacement Mutex....
Code:
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
How can I do to make this error disappear ?
Other question, in my code when i'm displaying threadID, it always displays 00000000159 (for example), for both threads ! I think I'm missing something.... Thread must NOT have the same ID ???? principles ??? (same problem in the two methods)
this is my code, without hpp files :
-------------------------------------------
Worker.cpp
Code:
Worker::Worker() { stopped = false;} // attribute of Worker instance
void Worker::process()
{
while (!stopped)
std::cout << messageStr.toStdString(); // attribute of Worker instance
emit finished();
}
void Worker::stop() { stopped = true;}
void Worker::start() {stopped = false;}
---------------------------------------------
ThreadDialog.cpp
Code:
{
workerA = new Worker();
workerB = new Worker();
quitButton->setDefault(true);
workerA->setMessage("A ");
workerA->moveToThread(threadA);
workerB->setMessage("B ");
workerB->moveToThread(threadB);
connect(threadA, SIGNAL(started()), workerA, SLOT(process()));
connect(workerA, SIGNAL(finished()), threadA, SLOT(quit()));
//connect(workerA, SIGNAL(finished()), workerA, SLOT(deleteLater()));
//connect(threadA, SIGNAL(finished()), threadA, SLOT(deleteLater()));
connect(threadB, SIGNAL(started()), workerB, SLOT(process()));
connect(workerB, SIGNAL(finished()), threadB, SLOT(quit()));
//connect(workerB, SIGNAL(finished()), workerB, SLOT(deleteLater()));
//connect(threadB, SIGNAL(finished()), threadB, SLOT(deleteLater()));
connect(threadAButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadA()));
connect(threadBButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadB()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
.... // displayLayout
}
void ThreadDialog::startOrStopThreadA()
{
if (threadA->isRunning())
{
workerA->stop();
threadAButton->setText(tr("Start A"));
}
else
{
std::cout << threadA->currentThreadId() << std::endl;
workerA->start();
threadA->start();
threadAButton->setText(tr("Stop A"));
}
}
void ThreadDialog::startOrStopThreadB()
{
if (threadB->isRunning())
{
workerB->stop();
threadBButton->setText(tr("Start B"));
}
else
{
std::cout << threadB->currentThreadId() << std::endl;
workerB->start();
threadB->start();
threadBButton->setText(tr("Stop B"));
}
}
{
workerA->stop();
workerB->stop();
threadA->wait();
threadB->wait();
threadA->exit();
threadB->exit();
event->accept();
}
Please Help me to understand QThread features... :(
Thank you
GuiHanoi
Re: QThread Proper Use ?? connect Problems....
Quote:
Originally Posted by
GuiHanoi
Both options are OK, it depends on what the thread does.
The first is the better option for something that is a single, long operation, the second is a good option for things that need events while processing.
Quote:
Originally Posted by
GuiHanoi
I developed a small project with these two methods to compare them. threadA which displays "A" and threadB which displays "B". To start/stop each threads, there are buttons. Both of these methods work (displaying AAAAA when AButton pushed, BBBBBBB when BButton pushed and ABABABABABA when both are pushed...
I personally would chose option 1 for that, way easier IMHO.
Quote:
Originally Posted by
GuiHanoi
but when I add these two connections, I have : Violation of Ox0FFFFFFFF emplacement Mutex....
Code:
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
At which of the two connects to you get the error?
It looks fine.
Quote:
Originally Posted by
GuiHanoi
Other question, in my code when i'm displaying threadID, it always displays 00000000159 (for example), for both threads ! I think I'm missing something.... Thread must NOT have the same ID ???? principles ??? (same problem in the two methods)
Your worker code does not output any thread ID, you only ever write the main thread's ID in the dialog code.
Quote:
Originally Posted by
GuiHanoi
Worker.cpp
Code:
Worker::Worker() { stopped = false;} // attribute of Worker instance
void Worker::process()
{
while (!stopped)
std::cout << messageStr.toStdString(); // attribute of Worker instance
emit finished();
}
void Worker::stop() { stopped = true;}
void Worker::start() {stopped = false;}
Concurrent access to members by multiple threads needs to be serialized, e.g. by using a mutex.
Here that is the access to "stopped", which is accessed by the worker thread in process() and by the main thread in stop() and start().
Quote:
Originally Posted by
GuiHanoi
Code:
{
workerA->stop();
workerB->stop();
threadA->wait();
threadB->wait();
threadA->exit();
threadB->exit();
event->accept();
}
QThread::exit() doesn't make much sense here. When wait() returns the thread has already exited.
Cheers,
_
Re: QThread Proper Use ?? connect Problems....
Hi,
Thank you for your fast but helpful answer !
In my case, I have to display camera data stream (for visualization) into a QLabel but still use GUI (buttons or process, etc.). So I heard you well, I have to choose the second option. (Currently, I had implemented the first method in my solution, but I noticed that it has low performance (200 to 300ms refreshing cycle however camera has only 50ms exposure time...) but didn't crash. So I thought that I was mistaken somewhere.
if I only write : connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater());
When I click on start button, it displays A correctly, and when I click on Stop button, it stops displaying A. OK Correct functionality
But when I click one again on start button, I have an Exception HeapAlloc (malloc.c).
if I only write : connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater());
Correct functionality until I click once again on start button : Ecxeption 5DB3CCAE (QtCored4.dll), emplacement Violation (qmutex.cpp) QMutex::lock()
If I'm writing these two lines : same error QMutex::lock()
I thought that because of my TWO Worker declarations, I didn't have to put Mutex protection. Why do I have to do that ? because "stopped" member is not shared with threadA and B because there are two Workers... ??
So I wrote QThread::currentThreadId() in Worker process method and Yes I have now several ID numbers of thread, but each time a different. :s I thought that there were my two threads that were doing the action and so I had thought I would only see two ID numbers.. maybe because of this line : connect(worker, SIGNAL(finished()), thread, SLOT(quit()) ????
Ok for the dispensable exit() !
Thank you
Thanks
Re: QThread Proper Use ?? connect Problems....
Quote:
Originally Posted by
GuiHanoi
In my case, I have to display camera data stream (for visualization) into a QLabel but still use GUI (buttons or process, etc.). So I heard you well, I have to choose the second option.
If you like that option better, go for it.
I would be using option one.
Quote:
Originally Posted by
GuiHanoi
if I only write : connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater());
When I click on start button, it displays A correctly, and when I click on Stop button, it stops displaying A. OK Correct functionality
But when I click one again on start button, I have an Exception HeapAlloc (malloc.c).
Ah, so the crash does not happen at connect. That was puzzling me.
That you crash on second start() is understandable, you are calling a method on an invalid pointer (the object got delete).
Quote:
Originally Posted by
GuiHanoi
I thought that because of my TWO Worker declarations, I didn't have to put Mutex protection. Why do I have to do that ? because "stopped" member is not shared with threadA and B because there are two Workers... ??
The member is accessed by the respective worker thread and the main thread.
Alternatively to implementing that correctly with a mutex, you could also use QThread::isInterruptionRequested() in the loop and QThread::requestInterruption() instead of stop().
Quote:
Originally Posted by
GuiHanoi
So I wrote QThread::currentThreadId() in Worker process method and Yes I have now several ID numbers of thread, but each time a different. :s I thought that there were my two threads that were doing the action and so I had thought I would only see two ID numbers.. maybe because of this line : connect(worker, SIGNAL(finished()), thread, SLOT(quit()) ????
When you call QThread::start() it will get a new thread from the operating system at let it handle run(), which in your case just emits started() and runs process().
Cheers,
_
Re: QThread Proper Use ?? connect Problems....
Thank you for your answers,
now I understand better QThread class and its functionality. last question. Is this a problem not to call deleteLater() for a thread ?
Thanks
Re: QThread Proper Use ?? connect Problems....
If your thread exists for the whole life time of the program, then you don't necessarily have to manually delete it.
deleteLater() is used here only to remove it once it has finished, but you could also ask it to stop, wait for it to be stopped and then delete it with "delete" or let its QObject parent delete it (as long as you have stopped it before).
Cheers,
_