PDA

View Full Version : How to use mutex in Qt multithreaded application



arunkumaraymuo1
25th February 2013, 11:57
I am creating a multithreade application to read from multiple serial devices at a time and send data to a network. My application works but I am not sure about how to perfectly use mutex in my application.
My application crashes sometimes, So I used QMutex to solve the issue.

My code is given

I created a static mutex object


class MyApp : public QObject
{
Q_OBJECT

public:
explicit MyApp(QObject *parent = 0);
~MyApp();

static int s_iCount;
static QList<QString> s_resultList;

static bool s_bStopThreadFlag;

static QMutex m_mutex;
SerialDevice *objDevice;
QThreadEx *objDeviceThread;

void removeDeviceConnction();
void startDeviceReading();



signals:
void exitThread();
void sendInstructionToDevice(QString strInstructions);

private:

QString m_strResultFull;


};


MyApp::MyApp(QObject *parent) :
QObject(parent),
m_iDeviceReadingInterval(1000)
{

// m_mutex.lock();
s_iCount = 0;
s_bStopThreadFlag = false;
// m_mutex.unlock();
startDeviceReading();
// timerSendDataDelay->start();
}


void MyApp::startDeviceReading()
{


QList<QextPortInfo> portlist = portinfo.getPorts();

for(int iCount = 0; iCount < portlist.count(); iCount++)
{


objDeviceThread= new QThreadEx();
objDevice = new SerialDevice(portlist[iCount].portName, 0);
objDevice->setReadingInterval(m_iDeviceReadingInterval);

connect(this, SIGNAL(exitThread()), objDevice, SLOT(finishWork()));
connect(this, SIGNAL(setReadingInterval(int)), objDevice, SLOT(setReadingInterval(int)));
connect(this, SIGNAL(sendInstructionToDevice(QString)), objDevice, SLOT(sendInstructionToDevice(QString)));
connect(this, SIGNAL(startReadingTimer()), objDevice, SLOT(startReadingTimer()));


objDevice->m_strPortName = portlist[iCount].portName;
objDevice->connect(objDeviceThread,
SIGNAL(started()),
SLOT(produce()));

objDevice->moveToThread(objDeviceThread);
objDeviceThread->start();
}
}


Created the thred object and started the thred


And in my serial device class accesses the static variables and static mutex like this



void SerialDevice::produce()
{


// MyApp::m_mutex.lock();
MyApp::s_iCount++;
m_iThredCount = MyApp::s_iCount;
MyApp::s_resultList.append("null");
MyApp::s_ValueList.append("null");
//MyApp::m_mutex.unlock();

PortSettings settings = {BAUD19200, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10};
m_port = new QextSerialPort(m_strPortName, settings, QextSerialPort::EventDriven);

timer = new QTimer(this);
timer->setInterval(20);

m_pagevalue = new char[20];

connect(timer, SIGNAL(timeout()), SLOT(onReadyRead()));
connect(m_port, SIGNAL(readyRead()), SLOT(onReadyRead()));

if (!m_port->isOpen())
{
m_port->setPortName(m_strPortName);
m_port->open(QIODevice::ReadWrite);
}


if (m_port->isOpen() && m_port->queryMode() == QextSerialPort::Polling)
timer->start();
else
timer->stop();
}

void SerialDevice::onReadyRead()
{
m_strData = "";
if (m_port->bytesAvailable())
{

m_strData = m_port->readAll();


// MyApp::m_mutex.lock();
MyApp::s_ValueList.replace(m_iThredCount - 1, strReadings);
// MyApp::m_mutex.unlock();

}
}

arunkumaraymuo1
27th February 2013, 05:04
Please help me :crying:

wysota
27th February 2013, 09:20
There are a lot of problems in your code.

A couple of things:
1. Why are you creating a separate thread for each device?
2. Why are you creating a new timer object every time produce() is called?

arunkumaraymuo1
27th February 2013, 12:03
Many thanks to your reply..,

I am developing an application that will read some USB devices at a time in a particular time interval. So I created a thread for each device that will read the USB device itself and it will add to an array. produce() is nothing I just used it for opening the USB port after creating the object. The functionalities are working but it crashes sometime.

wysota
27th February 2013, 12:14
I am developing an application that will read some USB devices at a time in a particular time interval. So I created a thread for each device that will read the USB device itself and it will add to an array.
There is no implication between your first sentence and your second sentence. In other words your first sentence doesn't explain your second sentence. In other words developing an application that will read some USB devices at a time in a particular time interval doesn't explain why you use threads.


produce() is nothing I just used it for opening the USB port after creating the object.
So why did you post it here? Post relevant code, not random code.

arunkumaraymuo1
27th February 2013, 13:48
I am not much familiar with threads in Qt.I am not able to put my full project here so i just pasted the parts of code that uses threds in my program. What happends when I create threads like this.


QList<QextPortInfo> portlist = portinfo.getPorts();

for(int iCount = 0; iCount < portlist.count(); iCount++)
{


objDeviceThread= new QThreadEx();
objDevice = new SerialDevice(portlist[iCount].portName, 0);
objDevice->setReadingInterval(m_iDeviceReadingInterval);

objDevice->moveToThread(objDeviceThread);
objDeviceThread->start();
}

wysota
27th February 2013, 14:09
This code is perfectly fine.

arunkumaraymuo1
28th February 2013, 05:01
Where is the issue?

ChrisW67
28th February 2013, 08:24
We cannot possibly know why your program crashes; possibly a null/dangling pointer, possibly not. Run it in a debugger and, when it crashes, read the stack trace to find out where it crashes in your code. Then you might have a chance of discovering why it crashes by inspecting variables involved at the time. We cannot do any of these things for you.

This would be a much easier thing to do if you were not using threads where threads are not required. Let the serial port tell you when it has data using the signals QextSerialPort gives you, buffer the data, and look at the buffers when you need to update a UI or whatever. All done in one thread.

arunkumaraymuo1
28th February 2013, 09:13
Somtime it shows the error
(process:2252) : GLib-ERROR **: Creating pipes for GWakeup: Too many open files