QSerialPort in another thread. Doesn't report errors...



  • Hi all. I am developing a GUI which will communicate to some hardware over a virtual serial port (USB to serial cable). I want to detect when the cable is disconnected. I have loaded the terminal example in QT creator and when I open the virtual serial port and then unplug it from the computer, an error is triggered, which is the correct behavior. I want my program to do the same thing.

    The thing is, I want to make a class that runs in a separate thread which contains a QSerialPort object and handles communication using this QSerialPort object. I want to connect the error signal from the QSerialPort class to my own error handler in my new class. The problem I have is that the error signal is never triggered with the right signal (QSerialPort::ResourceError)! In the terminal example program, this signal is correctly generated.

    I think this is some sort of thread affinity issue. If I instead make the QSerialPort object a member of the mainwindow class and then connect the serial port object's error signal to a member slot of mainwindow, everything works A-OK when I rip the USB cable from my computer. Any ideas?



  • Also, this is my first time using QThreads. My mainwindow constructor does the following to set up the SSACom2 object (the object that has a Qserialport and handles connection stuff at a higher level): cThread is member of my MainWindow class.

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    cThread = new QThread(this);

    scom = new SSAComm2(NULL);
    
    scom->doSetup(cThread);
    scom->moveToThread(cThread);
    
    cThread->start();
    

    }


  • Moderators

    Hi,

    Can you show us the code inside SSAComm2::doSetup()?



  • Yes. ssacomm2.cpp:

    #include "ssacomm2.h"
    #include <QDebug>

    SSAComm2::SSAComm2(QObject *parent) : QObject(parent)
    {

    }

    SSAComm2::~SSAComm2()
    {

    }

    void SSAComm2::doSetup(QThread *cThread)
    {
    connect(cThread, SIGNAL(started()), this, SLOT(doWork()));
    thisThread = cThread;
    port = new QSerialPort(this);
    port->setPortName("COM3");
    port->open(QIODevice::ReadWrite);
    connect(port, SIGNAL(error(QSerialPort::SerialPortError)), this,
    SLOT(handleError(QSerialPort::SerialPortError)));
    qDebug() << "SSA Comm2 starting!";
    }

    void SSAComm2::doWork()
    {
    while(1);

    return;
    

    }

    void SSAComm2::handleError(QSerialPort::SerialPortError error)
    {
    if (error == QSerialPort::ResourceError) {
    qDebug() << "Error! Unplugged Cable!!!"; //This never executes when I unplug the USB cable!!!!
    }
    }


  • Moderators

    Hi,

    You have 2 problems:

    @zeneslev said:

    void SSAComm2::doSetup(QThread *cThread)
    {
        ...
        port = new QSerialPort(this);
        port->setPortName("COM3");
        port->open(QIODevice::ReadWrite);
        ...
    }
    

    1st problem: You created and opened the serial port in the main thread.

    You must call the QSerialPort constructor and open() in your worker thread.

    @zeneslev said:

    void SSAComm2::doWork()
    {
        while(1);
    
        return;
    }
    

    2nd problem: You have an infinite loop in doWork().

    When a thread is running an infinite loop, it cannot cannot process any signals because the infinite loop blocks the event loop.



  • @JKSH

    Thank you! I get the correct behavior now. My initial understanding about how threading works was incorrect. I was under the impression that the thread will end when doWork finishes, but that isn't the case. Thanks for taking a look!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.