在checkConn的 m_loop.exec(); 等待时 发生,闪退 报错:QThread: Destroyed while thread is still running,但是这个cpp中两个线程从代码分析 都没有要删除销毁的趋势,外部是通过
EcmApiDataSender sender;
if (!m_port.isEmpty())
{
sender.setPort(m_port);
}
QString uuid = sender.sendReq(callName, params);
调用
#include "EcmApiDataSender.h"
#include <nlohmann/json.hpp>
using std_json = nlohmann::json;
EcmApiDataSender::EcmApiDataSender()
{
if (!m_socketThread)
{
m_socketThread = new QThread();
m_socketThread->setObjectName("我是Sock线程");
m_socketThread->start();
}
if (!m_invoker) {
m_invoker = new EcmApiSocketInvoker();
m_invoker->moveToThread(m_socketThread);
connect(m_invoker, SIGNAL(sendFailed(qint64, const QString&)), this, SLOT(handleSendFailed(qint64, const QString&)), Qt::AutoConnection);
}
m_timer = new QTimer();
m_timerThread = new QThread();
m_timerThread->setObjectName("我是timer");
connect(m_timerThread, &QThread::started, [&] {
m_timer->start(m_socketTimeout);
});
connect(m_timerThread, &QThread::finished, m_timer , &QTimer::stop);
connect(m_timerThread, &QThread::destroyed, m_timer, &QTimer::deleteLater);
}
EcmApiDataSender& EcmApiDataSender::getInstance()
{
static EcmApiDataSender ins;
return ins;
}
EcmApiDataSender::~EcmApiDataSender()
{
LOG(INFO)<<"EcmApiDataSender析构函数start";
disConn();
if (m_timerThread)
{
m_timerThread->requestInterruption();
m_timerThread->quit();
QThread::msleep(100);
m_timerThread->deleteLater();
}
if (m_socketThread) {
m_socketThread->requestInterruption();
m_socketThread->quit();
QThread::msleep(100);
m_socketThread->deleteLater();
}
LOG(INFO)<<"EcmApiDataSender析构函数";
}
void EcmApiDataSender::conn()
{
if (!m_socket)
{
LOG(INFO)<<"new Conn";
m_socket = new QWebSocket();
m_socket->moveToThread(m_socketThread);
connect(m_socketThread, &QThread::finished, m_socket, &QObject::deleteLater);
connect(m_socketThread, &QThread::finished, this, &EcmApiDataSender::handle1);
connect(this, SIGNAL(sendMessage(QWebSocket*, const QString&)), m_invoker, SLOT(sendMessage(QWebSocket*, const QString&)), Qt::AutoConnection);
connect(this, SIGNAL(open(QWebSocket*, const QString&)), m_invoker, SLOT(open(QWebSocket*, const QString&)), Qt::AutoConnection);
connect(this, SIGNAL(close(QWebSocket*)), m_invoker, SLOT(close(QWebSocket*)), Qt::AutoConnection);
connect(m_socket, &QThread::destroyed, m_invoker, &EcmApiSocketInvoker::deleteLater,Qt::AutoConnection);
}
LOG(INFO) << "socket connect";
QUrl local(m_url);
connect(m_socket, SIGNAL(textMessageReceived(QString)), this, SLOT(handleMessageReceived(QString)), Qt::AutoConnection);
connect(m_socket, SIGNAL(connected()), this, SLOT(handleConnected()), Qt::AutoConnection);
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(handleError(QAbstractSocket::SocketError)), Qt::AutoConnection);
connect(m_timer, SIGNAL(timeout()), this, SLOT(handleTimeout()), Qt::AutoConnection);
//connect(m_timerThread, &QThread::destroyed, this, &EcmApiDataSender::handle1,Qt::AutoConnection);
connect(m_socketThread, &QThread::destroyed, this, &EcmApiDataSender::handle2,Qt::AutoConnection);
connect(m_socket, &QThread::destroyed, this, &EcmApiDataSender::handle3,Qt::AutoConnection);
m_connReport = false;
m_timer->moveToThread(m_timerThread);
m_timerThread->start();
emit open(m_socket, m_url);
}
void EcmApiDataSender::disConn()
{
LOG(INFO) << "socket disconnect";
if (m_socket && m_socket->isValid())
{
emit close(m_socket);
}
}
void EcmApiDataSender::checkConn()
{
LOG(INFO) << "检测桥接服务连接状态";
if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState)
{
LOG(INFO) << "检测到未连接,开始连接桥接服务";
m_locker.lockForWrite();
conn();
m_loop.exec();
m_locker.unlock();
if (!m_connReport) {
LOG(INFO) << "连接失败";
}
}
LOG(INFO) << "连接正常";
}
QString EcmApiDataSender::getRetMsg(const QString& uuid)
{
m_locker.lockForRead();
QString retMsg = m_retMsg[uuid].toString();
m_locker.unlock();
return retMsg;
}
bool EcmApiDataSender::hasResult(const QString& uuid)
{
m_locker.lockForRead();
if (m_retMsg.contains(uuid))
{
m_locker.unlock();
return true;
}
m_locker.unlock();
return false;
}
QString EcmApiDataSender::sendReq(const QString& callName, const QString& params)
{
cleanResult();
checkConn();
QString uuid = QUuid::createUuid().toString().remove("{").remove("}").remove("-");
QJsonObject obj;
obj["method"] = callName;
obj["params"] = params;
obj["guid"] = uuid;
QJsonDocument doc;
doc.setObject(obj);
auto sendMsg = doc.toJson();
LOG(INFO) << "sendmessage:" << sendMsg.toStdString();
emit sendMessage(m_socket, sendMsg);
return uuid;
}
void EcmApiDataSender::setUrl(const QString& url)
{
m_url = url;
}
void EcmApiDataSender::setPort(const QString& port)
{
m_url = m_defaultUrl.replace("<port>", port);
m_port = port;
}
QString EcmApiDataSender::getPort()
{
return m_port;
}
void EcmApiDataSender::setSocketTimeout(int timeout)
{
m_socketTimeout = timeout;
}
void EcmApiDataSender::quitWait()
{
if (m_loop.isRunning()) {
m_loop.quit();
m_timerThread->quit();
}
}
void EcmApiDataSender::cleanResult()
{
if (!m_retLifeTime.isEmpty()) {
m_locker.lockForWrite();
auto deadTime = QDateTime::currentDateTime().addSecs(-2);
for (auto it = m_retLifeTime.begin(); it != m_retLifeTime.end(); ) {
if (it.value() < deadTime)
{
m_retMsg.remove(it.key());
m_retLifeTime.erase(++it);
continue;
}
it++;
}
m_locker.unlock();
}
}
void EcmApiDataSender::handleConnected()
{
LOG(INFO) << "连接成功";
m_connReport = true;
quitWait();
}
void EcmApiDataSender::handleError(QAbstractSocket::SocketError err)
{
QMetaEnum m = QMetaEnum::fromType<QAbstractSocket::SocketError>();
LOG(INFO) << "连接错误:" << m.value(err);
quitWait();
}
void EcmApiDataSender::handleTimeout()
{
if (m_loop.isRunning()) {
LOG(INFO) << "连接超时";
quitWait();
}
}
void EcmApiDataSender::handle1(){
LOG(INFO)<<"我被销毁了";
}
void EcmApiDataSender::handle2(){
LOG(INFO)<<"我被销毁了2";
}
void EcmApiDataSender::handle3(){
LOG(INFO)<<"我被销毁了3";
}
void EcmApiDataSender::handleSendFailed(qint64 ret, const QString& msg)
{
LOG(INFO) << "sendFailed retCode " << ret;
LOG(INFO) << "接收发送错误返回消息:" << msg.toStdString();
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(msg.toStdString().data(), &err);
if (err.error != QJsonParseError::NoError)
{
LOG(INFO) << "报文转换失败,内容:" << msg.toStdString() << ",错误信息:" << err.errorString().toStdString();
return;
}
auto obj = doc.object();
auto guid = obj["guid"].toString();
if (guid.isEmpty())
{
LOG(INFO) << "报文解析失败:guid为空";
return;
}
m_locker.lockForWrite();
m_retMsg[guid] = "影像api调用失败";
m_retLifeTime[guid] = QDateTime::currentDateTime();
m_locker.unlock();
quitWait();
}
void EcmApiDataSender::handleMessageReceived(const QString& msg)
{
if (msg.isEmpty())
{
LOG(INFO) << "检测到空消息";
return;
}
LOG(INFO) << "接收返回消息:" << msg.toStdString();
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(msg.toStdString().data(), &err);
if (err.error != QJsonParseError::NoError)
{
LOG(INFO) << "报文转换失败,内容:" << msg.toStdString() << ",错误信息:" << err.errorString().toStdString();
return;
}
auto obj = doc.object();
auto guid = obj["guid"].toString();
if (guid.isEmpty()) {
LOG(INFO) << "报文解析失败:guid为空";
return;
}
auto message = obj["message"].toString();
m_locker.lockForWrite();
m_retMsg[guid] = message;
m_retLifeTime[guid] = QDateTime::currentDateTime();
m_locker.unlock();
}