You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt5中C++程序非Qt线程与Qt网络通信的警告问题

Qt5中QSslSocket跨线程访问导致QSocketNotifier警告的问题

基于Qt5开发的C++程序,通过QSslSocket与TCP/IP服务器通信,功能正常但持续弹出警告:

QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

程序连接流程

主线程中发起服务器连接:

devConnectionHandler::instance().connect( args[0].sval, args[1].sval )
// 内部调用Qt库方法
devResult status = dev_connect( name.c_str(), interface.c_str(), NULL );

dev_connect实现:

Q_UNUSED(reserved);
// 持有服务器通信套接字的QObject
DevHalRemote *hal = new DevHalRemote();
// 执行实际连接
const DevResult result = hal->DevConnect(name, interface);

if (result == DEV_OK) {
    m_RemoteList.insert(name, hal);
} else {
    delete hal;
}

return result;

DevHalRemote构造函数(创建QSslSocket):

DevHalRemote::DevHalRemote(QObject *parent) :
    QObject(parent)
{
    m_socket = new QSslSocket(this);
    m_socket->setProtocol(QSecureSslProtocols);
    m_socket->setPeerVerifyMode(QSslSocket::VerifyNone);
    m_socket->setProxy(QNetworkProxy::NoProxy);

    if (!QCoreApplication::instance())
        new QCoreApplication(g_argc, g_argv);
}

主线程数据访问逻辑

主线程初始化数据结构时调用:

DevItemProperty item = dev_getItemProperty( name, object ) 

dev_getItemProperty实现:

devItemProperty dev_getItemProperty(const char *name, const char *object)
{
    DevHalRemote *hal = m_halRemoteList.value(name);
    return hal->GetItemProperty(object);
}

DevHalRemote中数据读写调用链:

DevItemProperty DevHalRemote::GetItemProperty(const QByteArray &item)
{
    const QByteArray data = writeRead(DEV_REMOTE_GETPROPERTY, item);
    if (data.isEmpty())
        return DEV_ERROR;

    DevItemProperty result;
    memcpy(&result, data.constData(), sizeof(DevItemProperty));
    return result;
}

QByteArray DevHalRemote::writeRead(char command, const QByteArray &value) const
{
    QByteArray write = command;
    if (!value.isEmpty())
        write += ';' + value;
    const QByteArray read = writeReadSynchronous(write);
    return read;
}

QByteArray DevHalRemote::writeReadSynchronous(const QByteArray &data) const
{
    m_socket->write(data);
    if (!m_socket->waitForBytesWritten(timeout()))
        return QByteArray();

    m_socket->waitForReadyRead(timeout());
    const QByteArray read = m_socket->readAll();

    QCoreApplication::instance()->processEvents();

    return read;
}

问题触发点:自定义pthread的跨线程访问

程序创建独立pthread监听Web界面修改,其run()方法中循环调用数据访问接口:

void devHalThread::run() {
  while( true ) {
  // devHal_info_t是自定义数据结构的typedef
    std::list<devHal_info_t*>::iterator it = _recs.begin();
    if( _pause > 0. ) this->thread.sleep( _pause );

    if( !_run ) continue;

    // 性能统计
    struct timespec start;
#ifdef _POSIX_CPUTIME
    clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &start );
#else
    clock_gettime( CLOCK_MONOTONIX, &start );
#endif
 //printf( "DevHalThread::run: Reading item '%s'\n", (*it)->object );

    for( ; it != _recs.end(); ++it ) {
     /* 此调用触发QtSocketNotifier警告*/
      DevItemProperty item = dev_getItemProperty( (*it)->interface, (*it)->object);
      if( strcmp( item.quality, Dev_ITEM_QUALITY_OK ) != 0 ) continue;
        // DevHAL中值已更新
        memcpy( (*it)->value, item.value, VALUE_SIZE );
        (*it)->time = time;
        callbackRequest( (*it)->pcallback );
      }
    }
}

问题核心:该pthread并非Qt线程,直接调用会在套接字创建线程(主线程)外访问QSslSocket,触发跨线程操作Qt对象的警告。

尝试的解决方案及新问题

尝试用QMetaObject::invokeMethod切换到Qt线程调用:

  1. 给DevHalRemote添加槽函数:
Q_SLOT DevItemProperty devhal_getItem(const QString s);

DevItemProperty devhal_getItem(const QString object){
  DevItemProperty item = GetItemProperty(object.toUtf8());
  return item;
}
  1. 修改pthread中的调用逻辑:
QString object((*it)->object);
QMetaObject::invokeMethod(halCon.hal_interface,
                         "devhal_getItem",
                         Qt::DirectConnection,
                         Q_RETURN_ARG(DevItemProperty, item),
                         Q_ARG(QString, object)
                         );
  • 使用Qt::DirectConnection:调用可执行,但警告仍存在;
  • 使用Qt::QueuedConnection:线程冻结,无数据更新。

需要找到消除警告同时保证功能正常的解决方案。

内容的提问来源于stack exchange,提问作者Yann Stephen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:44:58