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

it troubles me !!!! QserialPort



  • a thread problme appear in my code
    STATUS/1 @ init, L120: BaudRate: 230400QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QSerialPort(0x2952c7b8), parent's thread is QThread(0x259e38f0), current thread is QThread(0x14cc2e0)

    my code :
    HardDriver*
    PlatformManager::addHardDriver(uint8_t driver_type, const char* device_port,
    uint32_t baudrate)
    {
    #ifdef QT
    if (driver_type == PlatformManager::SERIAL_DEVICE)
    {

    QThread*     serialEventThread = new QThread;
    QHardDriver* driver            = new QHardDriver(0, device_port, baudrate);
    driver->moveToThread(serialEventThread);
    QObject::connect(serialEventThread, SIGNAL(started()), driver,
                     SLOT(init()));
    QObject::connect(serialEventThread, SIGNAL(finished()), serialEventThread,
                     SLOT(deleteLater()));
    serialEventThread->start();
    QThread::msleep(100);
    return driver;
    

    }


    void
    QHardDriver::init()
    {
    initLock.lock();
    if (this->getDeviceStatus())
    {
    initLock.unlock();
    return;
    }

    port = new QSerialPort(QString(portName));
    if (port != 0)
    {
    if (port->isOpen())
    port->close();
    port->setBaudRate(baudrate);
    port->setParity(QSerialPort::NoParity);
    port->setDataBits(QSerialPort::Data8);
    port->setStopBits(QSerialPort::OneStop);
    port->setFlowControl(QSerialPort::NoFlowControl);
    if (port->open(QIODevice::ReadWrite))
    {
    DSTATUS("port %s open success", port->portName().toLocal8Bit().data());
    setDeviceStatus(true);
    DSTATUS("Read buf size: %d", port->readBufferSize());
    }
    else
    {
    DERROR("fail to open port %s", port->portName().toLocal8Bit().data());
    setDeviceStatus(false);
    }
    DSTATUS("BaudRate: %d", port->baudRate());
    }
    initLock.unlock();
    }


    but run there it throws a problem
    //! Serial Device call: last link in the send pipeline
    DERROR("*****1");
    ans = deviceDriver->send(buf, pHeader->length); // throws Cannot create children for a parent that is in a different thread.
    //(Parent is QSerialPort(0x2952c7b8), parent's thread is
    //QThread(0x259e38f0), current thread is QThread(0x14cc2e0)



  • This post is deleted!

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    What does happen in deviceDriver->send ?
    Where are you calling if from ?

    What version of Qt are you using ?
    What OS are you running ?



  • hi ~ thank you first
    it works on windows QT5.1

    HardDriver* deviceDriver;
    QHardDriver::send(const uint8_t* buf, size_t len)
    {
    sendLock.lock();
    size_t sent = 0;
    if (port != 0)
    {
    // if (port->isOpen())
    while (sent != len)
    {
    sent += port->write(reinterpret_cast<const char*>(buf + sent), len);
    port->waitForBytesWritten(2);
    }
    sendLock.unlock();
    return sent;
    }
    else
    {
    sendLock.unlock();
    return 0;
    }
    sendLock.unlock();
    return sent;
    }


  • Lifetime Qt Champion

    @quelle.shen said in it troubles me !!!! QserialPort:

    it works on windows QT5.1

    QSerialPort was very new in Qt 5.1. I strongly recommend updating to a newer version.

    That may not solve your problem, but avoid others.



  • @aha_1980
    maybe you are right ,but i have to run it on Qt5.1
    the problem still troubles me !!


  • Lifetime Qt Champion

    You seem to move your serial port stuff in another thread and then calling its methods directly, is that the case ?



  • @SGaist
    yes ,but i dont know how to revision my code.



  • @SGaist
    why just call port->write() will trows the problem ?
    i add some code but it doesnt work .
    i add code :


    QThread* serialEventThread = new QThread;
    QHardDriver* driver = new QHardDriver(0, device_port, baudrate);
    //driver->init();
    driver->moveToThread(serialEventThread);
    driver->port->moveToThread(serialEventThread);
    //Qt:: DirectConnection
    QObject::connect(serialEventThread, SIGNAL(started()), driver,
    SLOT(init()));
    QObject::connect(serialEventThread, SIGNAL(finished()), driver, SLOT(deleteLater()));
    QObject::connect(serialEventThread, SIGNAL(finished()), serialEventThread,
    SLOT(deleteLater()));
    serialEventThread->start();
    QThread::msleep(100);
    return driver;




  • @quelle.shen said in it troubles me !!!! QserialPort:

    QObject::connect(serialEventThread, SIGNAL(started()), driver,
    SLOT(init()));

    From our direct messages...

    hmm.... When you call deviceDriver->send(), I assume that send() is a member of deviceDriver?. But deviceDriver is in a different thread! in addHardDriver() you return a device driver that was moved to a different thread. What you need to do now is create another slot/signal connection to send your write-data to your device driver via a call to a signal. Somthing like: QObject::connect(this, SIGNAL(send_to_driver(QVector data)), driver,SLOT(data_to_send(QVector data))); Then instead of doing driver->write() you do send_to_driver(data). I used QVector in my example - not but you can put what ever Q<data type> you want...

    Note: You cannot ever safely call members directly in the device driver ever again once you have moved it into another thread :p ... this is exactly what slot/signals are for. Doing so breaks the thread boundaries and Qt rightfully complains. If you call a member function directly then everything that occurs in that function call occurs in the calling thread and not the thread that you moved that class into. Does that make sense?



  • @code_fodder
    thanks reply for my question ,you are right .
    i think your advice is good way to solve my problem .


Log in to reply