Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QSerialPort - opening port in non-blocking way causes readyRead not to be automatically emitted later on



  • Hello,

    When QSerialPort::open is called program (GUI) freezes for a little bit (~3-5s) for the port to open. I wanted to avoid this small inconvinience by opeining it async way and reporting the result. However I found out that later on this causes QIODevice::readyRead signal not to be emitted.

        connect(m_port, &QSerialPort::readyRead, []() { qDebug() << "ready read!"; });
        connect(m_port, &QSerialPort::bytesWritten, [](int i) { qDebug() << "bytes written" << i; });
    
        //this makes readyRead work
        //m_port->open(QIODevice::ReadWrite); 
    
        // and this not
        using FW = QFutureWatcher<bool>;
        FW *w = new FW();
        connect(w, &FW::started, this, &RJ6::setBusy);
        connect(w, &FW::finished, w, &FW::deleteLater);
        connect(w, &FW::finished, this, &RJ6::onOpenFinished);
        connect(w, &FW::finished, this, &RJ6::setIdle);
        connect(w, &FW::canceled, this, &RJ6::close);
    
        QFuture<bool> f = QtConcurrent::run([=]() { return m_port->open(QIODevice::ReadWrite); });
    
        w->setFuture(f);
    

    setBusy, setIdle, onOpenFinished are just emitting signals, nothing else is going on there.

    This piece of code is triggered on write request

      qInfo() << QTime::currentTime().toString("hh:mm:ss.zzz") <<  "----- new write request - prev one should be already read-ready reported ----";
      qInfo() << "write" << data.toHex() << m_port->write(data);
      qInfo() << "flush" << m_port->flush();
      //qInfo() << "read all" << m_port->readAll().toHex();
    

    And now I noticed that when I write data to the port, I need to manually read it since QIODevice::readyRead is not emmited autmatically, seems like only after I try QSerialPort::readAll port "realizes" that there is data available for reading

    SerialWidget::onSendClicked "02"
    "16:38:46.209" ----- new write request - prev one should be already read-ready reported ----
    write "02" 1
    flush true
    read all ""
    bytes written 1
    SerialWidget::onSendClicked "02"
    "16:38:58.218" ----- new write request - prev one should be already read-ready reported ----
    write "02" 1
    flush true
    read all ""
    bytes written 1
       ready read! <-------- this is only showed when I uncomment readAll() call
    SerialWidget::onSendClicked "02"
    "16:39:15.771" ----- new write request - prev one should be already read-ready reported ----
    write "02" 1
    flush true
    read all "52454a3030364a4417"
    bytes written 1
       ready read! <-------- this is only showed when I uncomment readAll() call
    

    However when I just stick to the blocking way of simply calling m_port->open(QIODevice::ReadWrite) without any QFuture fanciness all works perfectly - readyRead is emitted correctly.

    Do you know what is wrong here?

    Environment: Qt\5.15.0\msvc2019_64 @ Win10



  • so if there is a delay during open, why do the open() in the main thread? Why not offload it and check the status when the worker thread completes?



  • @Kent-Dorfman
    That is basically what I did! I mean - I don't explicitly create another thread, I just run QSerialPort::open on, what I understood from the docs, one of the threads from the global pool (QThreadPool::globalInstance()). I don't understand why this has influence on QSerialPort::readyRead signal.


  • Lifetime Qt Champion

    Hi,

    You did just move the open call to another thread. What @Kent-Dorfman suggest is to implement a worker object to full manage your serial port in another thread.



  • Yes, I understand the idea. However I thought that this will be not necessary - I am using readyRead/bytesWritten to communicate with the device and it was working fine for me - no other thread was needed - until this open thing poped up.

    Alright, I assume either a little lag on open is acceptable or rewriting while thing to be handled in separate thread is necessary...


  • Lifetime Qt Champion

    The fact that your serial port opens slowly does not mean there's a bug in Qt. Did you check with another application whether it behaves the same ?



  • @SGaist said in QSerialPort - opening port in non-blocking way causes readyRead not to be automatically emitted later on:

    The fact that your serial port opens slowly does not mean there's a bug in Qt.

    Is it related to this bug?

    Environment: Qt\5.15.0\msvc2019_64 @ Win10

    Ahh. no..

    Most likelly the problem is in your HW device or driver. Also you should not call the QSP methods from the different threads (as daid before).



  • @SGaist I did not say that there is a bug, to be honest I was quiet sure that it is me who is doing something wrong. And yes - I tried Bluetooth Serial Terminal (from Win10 store) and it also takes a few seconds to connect to device as well. I assume it might be the device (it is a custom thing I'd say) that lags on open.

    Alright, at least I understand now that either I need to move all the stuff to some kind of worker handling QSP on separate thread or accept that there will be a lag on open.

    Thanks, guys!


Log in to reply