I have a Qt Application which works on high frequency data, I am receiving data of around 2kb every 30ms, but what happens is the application becomes unresponsive.
<code>#ifndef UDPHANDLER_H
#define UDPHANDLER_H
#include <QObject>
#include <QUdpSocket>
#include <QThread>
#include <QHostAddress>
#include <QElapsedTimer>
class UdpSocketHandler : public QObject
{
Q_OBJECT
public:
explicit UdpSocketHandler(QObject *parent = nullptr);
~UdpSocketHandler();
void bindSocket(const QHostAddress &address, quint16 port);
public slots:
void onReadyRead(); // Slot to handle the datagrams
private:
QUdpSocket *udpSocket;
QThread *workerThread; // Thread for the UDP handling
QElapsedTimer Elapsed_time;
};
#endif // UDPHANDLER_H
#include "udphandler.h"
#include "custom/data/DataFile.h"
#include <QDebug>
#include <QtConcurrent/QtConcurrent>
#include <QTimer>
UdpSocketHandler::UdpSocketHandler(QObject *parent)
: QObject(parent), udpSocket(nullptr), workerThread(new QThread(this))
{
}
void UdpSocketHandler::setupThread()
{
this->moveToThread(workerThread);
connect(workerThread, &QThread::started, this, &UdpSocketHandler::setupSocket);
workerThread->start();
}
UdpSocketHandler::~UdpSocketHandler()
{
if (workerThread->isRunning()) {
workerThread->quit();
workerThread->wait();
}
if (udpSocket) {
udpSocket->close();
delete udpSocket;
udpSocket = nullptr;
}
delete workerThread;
}
void UdpSocketHandler::setupSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 64 * 1024);
udpSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
if (udpSocket->bind(address, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) {
qWarning() << Q_FUNC_INFO << "Socket bound to Addr:" << address.toString() << "PORT:" << port;
connect(udpSocket, &QUdpSocket::readyRead, this, &UdpSocketHandler::onReadyRead);
} else {
qWarning() << Q_FUNC_INFO << "Failed to bind UDP socket. Addr:" << address.toString() << "PORT:" << port;
}
}
void UdpSocketHandler::bindSocket(const QHostAddress &m_address, quint16 m_port)
{
address = m_address;
port = m_port;
setupThread();
}
void UdpSocketHandler::onReadyRead()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
QtConcurrent::run([datagram]() {
aerx::readDataFromStruct(datagram);
});
datagram.clear();
}
}
//In main.cpp
UdpSocketHandler* udpHandler = new UdpSocketHandler();
udpHandler->bindSocket(QHostAddress(offsetSenderIP), offsetSenderPORT);
</code>
<code>#ifndef UDPHANDLER_H
#define UDPHANDLER_H
#include <QObject>
#include <QUdpSocket>
#include <QThread>
#include <QHostAddress>
#include <QElapsedTimer>
class UdpSocketHandler : public QObject
{
Q_OBJECT
public:
explicit UdpSocketHandler(QObject *parent = nullptr);
~UdpSocketHandler();
void bindSocket(const QHostAddress &address, quint16 port);
public slots:
void onReadyRead(); // Slot to handle the datagrams
private:
QUdpSocket *udpSocket;
QThread *workerThread; // Thread for the UDP handling
QElapsedTimer Elapsed_time;
};
#endif // UDPHANDLER_H
#include "udphandler.h"
#include "custom/data/DataFile.h"
#include <QDebug>
#include <QtConcurrent/QtConcurrent>
#include <QTimer>
UdpSocketHandler::UdpSocketHandler(QObject *parent)
: QObject(parent), udpSocket(nullptr), workerThread(new QThread(this))
{
}
void UdpSocketHandler::setupThread()
{
this->moveToThread(workerThread);
connect(workerThread, &QThread::started, this, &UdpSocketHandler::setupSocket);
workerThread->start();
}
UdpSocketHandler::~UdpSocketHandler()
{
if (workerThread->isRunning()) {
workerThread->quit();
workerThread->wait();
}
if (udpSocket) {
udpSocket->close();
delete udpSocket;
udpSocket = nullptr;
}
delete workerThread;
}
void UdpSocketHandler::setupSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 64 * 1024);
udpSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
if (udpSocket->bind(address, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) {
qWarning() << Q_FUNC_INFO << "Socket bound to Addr:" << address.toString() << "PORT:" << port;
connect(udpSocket, &QUdpSocket::readyRead, this, &UdpSocketHandler::onReadyRead);
} else {
qWarning() << Q_FUNC_INFO << "Failed to bind UDP socket. Addr:" << address.toString() << "PORT:" << port;
}
}
void UdpSocketHandler::bindSocket(const QHostAddress &m_address, quint16 m_port)
{
address = m_address;
port = m_port;
setupThread();
}
void UdpSocketHandler::onReadyRead()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
QtConcurrent::run([datagram]() {
aerx::readDataFromStruct(datagram);
});
datagram.clear();
}
}
//In main.cpp
UdpSocketHandler* udpHandler = new UdpSocketHandler();
udpHandler->bindSocket(QHostAddress(offsetSenderIP), offsetSenderPORT);
</code>
#ifndef UDPHANDLER_H
#define UDPHANDLER_H
#include <QObject>
#include <QUdpSocket>
#include <QThread>
#include <QHostAddress>
#include <QElapsedTimer>
class UdpSocketHandler : public QObject
{
Q_OBJECT
public:
explicit UdpSocketHandler(QObject *parent = nullptr);
~UdpSocketHandler();
void bindSocket(const QHostAddress &address, quint16 port);
public slots:
void onReadyRead(); // Slot to handle the datagrams
private:
QUdpSocket *udpSocket;
QThread *workerThread; // Thread for the UDP handling
QElapsedTimer Elapsed_time;
};
#endif // UDPHANDLER_H
#include "udphandler.h"
#include "custom/data/DataFile.h"
#include <QDebug>
#include <QtConcurrent/QtConcurrent>
#include <QTimer>
UdpSocketHandler::UdpSocketHandler(QObject *parent)
: QObject(parent), udpSocket(nullptr), workerThread(new QThread(this))
{
}
void UdpSocketHandler::setupThread()
{
this->moveToThread(workerThread);
connect(workerThread, &QThread::started, this, &UdpSocketHandler::setupSocket);
workerThread->start();
}
UdpSocketHandler::~UdpSocketHandler()
{
if (workerThread->isRunning()) {
workerThread->quit();
workerThread->wait();
}
if (udpSocket) {
udpSocket->close();
delete udpSocket;
udpSocket = nullptr;
}
delete workerThread;
}
void UdpSocketHandler::setupSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 64 * 1024);
udpSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
if (udpSocket->bind(address, port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) {
qWarning() << Q_FUNC_INFO << "Socket bound to Addr:" << address.toString() << "PORT:" << port;
connect(udpSocket, &QUdpSocket::readyRead, this, &UdpSocketHandler::onReadyRead);
} else {
qWarning() << Q_FUNC_INFO << "Failed to bind UDP socket. Addr:" << address.toString() << "PORT:" << port;
}
}
void UdpSocketHandler::bindSocket(const QHostAddress &m_address, quint16 m_port)
{
address = m_address;
port = m_port;
setupThread();
}
void UdpSocketHandler::onReadyRead()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
QtConcurrent::run([datagram]() {
aerx::readDataFromStruct(datagram);
});
datagram.clear();
}
}
//In main.cpp
UdpSocketHandler* udpHandler = new UdpSocketHandler();
udpHandler->bindSocket(QHostAddress(offsetSenderIP), offsetSenderPORT);
Note that the problem is with udp connection only, if i update data from while loop “without UDP connection” everything works as expected but updating same thing through udp connection makes whole application unresponsive
<code> connect(timerForTest, &QTimer::timeout, this, [this](){
aerx::setMapVal(KEY_PitchVal, pitch);
aerx::setMapVal(KEY_YawVal, yaw);
aerx::setMapVal(KEY_RollVal, roll);
pitch += i_pitch;
yaw += i_yaw;
roll += i_roll;
if(pitch >= 90 || pitch <= -90)
i_pitch *= -1;
if(yaw >= 180 && yaw <= -180)
i_yaw *= -1;
if(roll >= 50 || roll <= -50)
i_roll *= -1;
});
//timerForTest->start(33); /* uncomment this, to test smoothness of PFD UI update without data coming from simulator */
</code>
<code> connect(timerForTest, &QTimer::timeout, this, [this](){
aerx::setMapVal(KEY_PitchVal, pitch);
aerx::setMapVal(KEY_YawVal, yaw);
aerx::setMapVal(KEY_RollVal, roll);
pitch += i_pitch;
yaw += i_yaw;
roll += i_roll;
if(pitch >= 90 || pitch <= -90)
i_pitch *= -1;
if(yaw >= 180 && yaw <= -180)
i_yaw *= -1;
if(roll >= 50 || roll <= -50)
i_roll *= -1;
});
//timerForTest->start(33); /* uncomment this, to test smoothness of PFD UI update without data coming from simulator */
</code>
connect(timerForTest, &QTimer::timeout, this, [this](){
aerx::setMapVal(KEY_PitchVal, pitch);
aerx::setMapVal(KEY_YawVal, yaw);
aerx::setMapVal(KEY_RollVal, roll);
pitch += i_pitch;
yaw += i_yaw;
roll += i_roll;
if(pitch >= 90 || pitch <= -90)
i_pitch *= -1;
if(yaw >= 180 && yaw <= -180)
i_yaw *= -1;
if(roll >= 50 || roll <= -50)
i_roll *= -1;
});
//timerForTest->start(33); /* uncomment this, to test smoothness of PFD UI update without data coming from simulator */
6