最近使用QModbusTCPClient通信,需要频繁发送读写请求,发现软件占用内存一直在增减,经过不断咨询和尝试,终于解决了。
1.方案一(失败)
最开始以为是访问太频繁,导致创建reply的对象比delete reply快导致的。尝试增加时间间隔,发现无效。内存占用还是在增加,只是增速慢了点。
QModbusReply*reply= m_modbus->sendReadRequest();
2.方案二(失败)
直接保存每个reply,只有reply==nullptr时才能重复发送对应的request()请求。在reply的finish槽函数中delete reply,同时让reply=nullptr。这样可以避免过于频繁的通信,确保前一次request()处理响应之后再次发送相同的request().
if(!m_reply[4]) //确保前一次响应处理之后再次发送相同的request()
{
QVector<quint16>values(1, 0);
QModbusDataUnit read(QModbusDataUnit::Coils, 128 + m_param->motorID(), values);
m_reply[4] = m_modbus->sendReadRequest(read, m_485ID);
if(m_reply[4] && !m_reply[4]->isFinished())
{
connect(m_reply[4], &QModbusReply::finished, [this]() {
if(m_reply[4]->error() == QModbusDevice::NoError)
{
m_runState = m_reply[4]->result().values().first();
}
delete m_reply[4];
m_reply[4] = nullptr;//确保下次可以再次发送request()
});
}
else {
delete m_reply[4];
m_reply[4] = nullptr;
}
}
仍然没有解决问题,内存还是在持续增加。
3.方案三(成功)
感谢这里的内容
https://bugreports.qt.io/browse/QTBUG-92072
问题:
//qmodbusclient_p.h ->enqueueRequest q->connect(q, &QModbusClient::timeoutChanged, element.timer.data(), QOverload<int>::of(&QTimer::setInterval));
QModbusTCPClient的每次request(无论读写)都会增加这样一个连接。即使销毁了对应的reply,也不能删除该链接,导致内存逐渐增加。
解决:
针对每一次request,手动断开该链接。
m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);
一段完整代码:
QModbusReply *reply = m_modbus->sendWriteRequest(
m_param->modbusData(topLeft),
m_485ID);
int id = m_param->index(topLeft.row(), m_param->IDCol).data().toInt();
int value = topLeft.data().toInt();
QString text = m_param->index(topLeft.row(), m_param->TextCol).data().toString();
if(reply && !reply->isFinished())
{
connect(reply, &QModbusReply::finished, [ = ]() {
if(reply->error() == QModbusDevice::NoError)
{
qInfo() << QString("MotorID:%1 Write(%2->%3(%4)) Succeed!\n")
.arg(m_param->motorID())
.arg(value)
.arg(id)
.arg(text);
}
else
{
qWarning() << QString("MotorID:%1 Write(%2->%3(%4)) Failed!\n")
.arg(m_param->motorID())
.arg(value)
.arg(id)
.arg(text);
}
//响应函数中手动断开连接
m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);
delete reply;
});
}
else
{
qWarning() << QString("MotorID:%1 Write(%2->%3(%4)) No Response!\n")
.arg(m_param->motorID())
.arg(value)
.arg(id)
.arg(text);
//响应函数中手动断开连接
m_modbus->disconnect(SIGNAL(timeoutChanged(int)), 0, 0);
delete reply;
}