Qt:QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread解决方法

在工作中使用QSerialPort+QThread时报出:QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread错误。相关代码如下:

void MainWindow::OnConnectionBtnClicked(void) // 一个按钮的槽函数
{
    bool bResult = false;

    m_pModbusMaster->moveToThread(m_pUartThread); // m_pModbusMaster是一个封装QSerialPort功能的类
    m_pModbusMaster->m_pUart->moveToThread(m_pUartThread);// m_pUartThread是一个QThread类
    bResult = m_pModbusMaster->m_pUart->Open(); // 打开串口操作,m_pUart是一个QSerialPort类

    if (bResult)
    {
        ui->disconnectionBtn->setEnabled(true);
        ui->connectionSettingBtn->setEnabled(false);
        ui->connectionBtn->setEnabled(false);
    }
    else
    {
        QMessageBox::critical(this, tr("critical"), QString(tr("%1打开失败!!!")).arg(m_pModbusMaster->m_pUart->m_pPort->portName()), QMessageBox::Yes);
    }
}

使用QSerialPort+QThread的目的是为了将串口的数据收发和主线程分开,从而避免主线程的卡顿。但是这段代码会报出如下错:
在这里插入图片描述
主要原因分析:在调用m_pModbusMaster->m_pUart->Open()打开串口之前,m_pModbusMaster、m_pUart对象已经被移动到了m_pUartThread子线程,而我的代码在主线程中进行子线程中对象的打开和关闭操作,会导致子线程对象的事件通知功能异常,所以报错。

解决方法:将m_pModbusMaster、m_pUart对象重新封装到一个新类中,在将该新类通过moveToThread方法移动到子线程中,然后通过在主线程中发送串口打开/关闭信号,子线程接收该信号并进行串口的打开和关闭操作。

新类:

class CCommunicationHandler : public QObject
{
    Q_OBJECT

public:
    CCommunicationHandler();
    ~CCommunicationHandler();

    /* 通信基类 */
    ModbusMaster *m_pModbusMaster;

signals:
	void OpenResult(Uint32 uiComMode, bool bResult);

public slots:
    void OnOpenRequestTrig(QString strSerialPortName, QSerialPort::BaudRate baudRate,
                           QSerialPort::Parity parity, QSerialPort::StopBits stopBits, QSerialPort::DataBits dataBits);

};

void CCommunicationHandler::OnOpenRequestTrig(QString strSerialPortName, QSerialPort::BaudRate baudRate, QSerialPort::Parity parity, QSerialPort::StopBits stopBits, QSerialPort::DataBits dataBits)
{
    m_uiComMode = 0;

    bool bResult = false;

    if (NULL == m_pModbusMaster)
    {
        m_pModbusMaster = new ModbusMaster(); // 对象创建也必须在子线程中
    }

    bResult = m_pModbusMaster->m_pUart->Open(strSerialPortName, baudRate, parity, dataBits, stopBits);

    emit OpenResult(m_uiComMode, bResult);
}

主函数中信号连接部分代码:

m_pcComHandler = new CCommunicationHandler();
m_pcComHandler->moveToThread(m_pUartThread);
m_pUartThread->start();

connect(this, SIGNAL(OpenRequest(QString, QSerialPort::BaudRate, QSerialPort::Parity, QSerialPort::StopBits, QSerialPort::DataBits)),
            m_pcComHandler, SLOT(OnOpenRequestTrig(QString, QSerialPort::BaudRate, QSerialPort::Parity, QSerialPort::StopBits, QSerialPort::DataBits)));
connect(m_pcComHandler, SIGNAL(OpenResult(Uint32, bool)), this, SLOT(OnOpenResult(Uint32, bool)));

原先的问题解决,但是还会引入新的问题
在这里插入图片描述
这是因为没有注册QSerialPort::BaudRate、QSerialPort::Parity、 QSerialPort::StopBits、 QSerialPort::DataBits对象(但是如果只有一个主线程的话就不需要)

解决方法:只需要在main函数中加入以下代码即可

    qRegisterMetaType<QSerialPort::BaudRate>("QSerialPort::BaudRate");
    qRegisterMetaType<QSerialPort::Parity>("QSerialPort::Parity");
    qRegisterMetaType<QSerialPort::StopBits>("QSerialPort::StopBits");
    qRegisterMetaType<QSerialPort::DataBits>("QSerialPort::DataBits");
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值