In QT multithreading, the problem that object signals and slots cannot be connected

In QT multithreading, the problem that object signals and slots cannot be connected

Reprinted: https://blog.csdn.net/xytx_823/article/details/51819474

There are many kinds of problems that cannot be connected, such as the parameter mismatch between the signal and the slot, the parameter is a custom type, and so on. A problem encountered today is that in multi-threading, signals and slots cannot be connected all the time. To prevent forgetting, record it.

The scenario of this problem is that a derived class of QObject is not created in the main thread, and then the derived class uses the default connection method to connect the signal, which cannot be connected at this time.

The root of the problem is that when connecting asynchronously, the signal is handled by the event processing mechanism of the thread where the receiver is located. If the thread where the receiver is located has no event handling, the signal will not be handled. Take a look at the code:

voidQCoreApplication::postEvent(QObject*receiver,QEvent*event, int priority)
{
    if (receiver == 0) {
        qWarning("QCoreApplication::postEvent: Unexpected null receiver");
        delete event;
        return;
    }
    QThreadData* volatile *pdata= &receiver->d_func()->threadData;
    QThreadData*data = *pdata;
    if (!data) {
        // postingduring destruction? just delete the event to prevent a leak
        delete event;
        return;
    }

    // lock the postevent mutex
    data->postEventList.mutex.lock();
    // if object hasmoved to another thread, follow it
    while (data != *pdata) {
        data->postEventList.mutex.unlock();
        data =*pdata;

        if (!data) {
            //posting during destruction? just delete the event to prevent a leak
            delete event;
            return;
        }
        data->postEventList.mutex.lock();
    }
    QMutexUnlockerlocker(&data->postEventList.mutex);
    // if this is oneof the compressible events, do compression
    if (receiver->d_func()->postedEvents
    && self&& self->compressEvent(event,receiver,&data->postEventList)){
        return;
    }



    if (event->type() ==QEvent::DeferredDelete&&data == QThreadData::current()) {
        // rememberthe current running eventloop for DeferredDelete
        // eventsposted in the receiver's thread
        static_cast<QDeferredDeleteEvent *>(event)->level =data->loopLevel;
    }

    // delete theevent on exceptions to protect against memory leaks till the event is
    // properly ownedin the postEventList
    QScopedPointer<QEvent>eventDeleter(event);
    data->postEventList.addEvent(QPostEvent(receiver,event, priority));
    eventDeleter.take();
    event->posted =true;
    ++receiver->d_func()->postedEvents;
    data->canWait =false;
    locker.unlock();
    QAbstractEventDispatcher*dispatcher =data->eventDispatcher.loadAcquire();
    if (dispatcher)
    dispatcher->wakeUp();
}

As can be seen from the above, the signal is packaged as an event and added to the event queue of the thread where the receiver is located.
Several solutions that come to mind temporarily:
1. In the receiver creation thread, move the receiver to the main thread:
pReceiverObj->moveToThread(QApplication::instance()->thread());
2. Send the signal like this At that time, it will be processed in the main thread event queue processing.
Change the last parameter of connect to Qt::DirectConnection, and use direct connection to connect signals and slots.
3. Start QThread's own event queue processing (exec()).
If there are any mistakes and problems, please advise.

The problem I am currently encountering is solved using the first method

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325409868&siteId=291194637