This question already has an answer here:
- Implementation of Inter Thread Communication in Qt 1 answer
I am new to C++ and Qt and I am having some trouble in achieving a good and not overcomplicated multithread communication environment.
Basically I have 3 threads, one for the GUI
, another for handling updates sent by a device
connected to the PC by USB, and another that will process the information acquired by the device
and control
the device
and the GUI
to change their state. So basically 3 threads: GUI
, device
and control
.
My fist approach was to have device
populate its private members with the information sent by USB and have some get()
methods that convert this data and return it (using mutexes to assure the data was still valid). The problem is when control
call the get()
methods in device
, it doesnt return anything new (I was expecting the methods to even never return since the thread is locked in another method, but they do return and with no new information, and also no breakpoints are triggered inside those get()
methods).
The usual way Qt does inter thread communications is by using Signal and Slots, but the problem with Signal and Slots is that when one thread is processing and it has a Slot, this Slot will never be executed if some Signal is sent. Even if I could manage to use Signal and Slots to trigger new data updates I am afraid there will be lots of Signals being sent since the device updates very fast, also I have lots of data types and using QAtomicInt will not be useful for many of them so my general question is which is the best way to make the threads share data and still keep running an infinite process loop?
A good example of my goal is having something like:
Control Thread:
while(true){
angle = device.getAngle(); //device is a member of control object and is running in a separate thread
doCalculations(angle);
}
Device Thread:
void process(){
while(true)
usbRead(data, size_of_data);
}
short getAngle(){
return (data[0] << 8 | data[1]);
}
I am not placing in this example the mutexes and etc, just a basic functionality to be expected.
As requested here is how I start my threads:
test::test(QWidget *parent) : QMainWindow(parent) , cvControl(device, 0)
{
//ui setup
connect(&device, SIGNAL(deviceConnected(bool)), this, SLOT(updateStatusConnection(bool)));
device.moveToThread(&deviceThread);
cvControl.moveToThread(&controlThread);
connect(&deviceThread, SIGNAL(started(void)), &device, SLOT(process(void)));
connect(&device, SIGNAL(deviceFinished(void)), &deviceThread, SLOT(quit(void)));
connect(&cvControl, SIGNAL(controlFinished(void)), &controlThread, SLOT(quit(void)));
connect(&deviceThread, SIGNAL(finished(void)), &device, SLOT(deleteLater(void)));
connect(&controlThread, SIGNAL(finished(void)), &cvControl, SLOT(deleteLater(void)));
connect(this, SIGNAL(startControlProcess(void)), &cvControl, SLOT(process(void)));
deviceThread.start();
controlThread.start();
}
void test::on_btnRun_clicked()
{
if(ui.btnRun->text() == "Run")
{
ui.btnRun->setText(QString("Stop"));
disbleControls();
emit startControlProcess();
}
else
{
ui.btnRun->setText(QString("Run"));
enableControls();
cvControl.abort.store(1);
}
}