Zoeken…


Qt gebruiken: DirectConnection wanneer het ontvangerobject geen signaal ontvangt

Soms zie je dat er een signaal wordt uitgezonden in de afzenderthread maar het verbonden slot roept niet (met andere woorden, het ontvangt geen signaal), je hebt erom gevraagd en uiteindelijk gekregen dat het verbindingstype Qt :: DirectConnection het zou repareren, dus het probleem is gevonden en alles is in orde.

Maar over het algemeen is dit een slecht idee om Qt: DirectConnection te gebruiken totdat u echt weet wat dit is en er geen andere manier is. Laten we het meer uitleggen, elke thread gemaakt door Qt (inclusief hoofdthread en nieuwe threads gemaakt door QThread) hebben Event loop, de event loop is verantwoordelijk voor het ontvangen van signalen en roept passende slots in zijn thread aan. Over het algemeen is het uitvoeren van een blokkeerbewerking in een slot een slechte gewoonte, omdat het de gebeurtenislus van die threads blokkeert, zodat er geen andere slots worden aangeroepen.

Als u een gebeurtenislus blokkeert (door zeer tijdrovende of blokkerende handelingen te verrichten), ontvangt u geen gebeurtenissen op die thread totdat de gebeurtenislus wordt gedeblokkeerd. Als de blokkeerbewerking de gebeurtenislus voor altijd blokkeert (zoals bezet terwijl), kunnen de slots nooit worden aangeroepen.

In deze situatie kunt u het verbindingstype instellen in connect to Qt :: DirectConnection, nu worden de slots opgeroepen, zelfs als de gebeurtenislus wordt geblokkeerd. dus hoe dit alles kapot kon maken? In Qt :: worden DirectConnection-slots in emiter-threads genoemd, en niet in ontvanger-threads. Dit kan gegevenssynchronisaties verbreken en andere problemen tegenkomen. Gebruik dus nooit Qt :: DirectConnection tenzij u weet wat u doet. Als je probleem wordt opgelost met Qt :: DirectConnection, moet je goed opletten en naar je code kijken om erachter te komen waarom je eventlus is geblokkeerd. Het is geen goed idee om de gebeurtenislus te blokkeren en het wordt niet aanbevolen in Qt.

Hier is een klein voorbeeld dat het probleem laat zien, omdat je kunt zien dat de nonBlockingSlot zelfs de blockingSlot geblokkeerde event-lus met while (1) wordt genoemd, wat een slechte codering aangeeft

class TestReceiver : public QObject{
    Q_OBJECT
public:
    TestReceiver(){
         qDebug() << "TestReceiver Constructed in" << QThread::currentThreadId();
    }
public slots:
    void blockingSlot()
    {
        static bool firstInstance = false;
        qDebug() << "Blocking slot called in thread" << QThread::currentThreadId();
        if(!firstInstance){
            firstInstance = true;
            while(1);
        }
    }
    void nonBlockingSlot(){
        qDebug() << "Non-blocking slot called" << QThread::currentThreadId();
    }
};

class TestSender : public QObject{
    Q_OBJECT
public:
    TestSender(TestReceiver * receiver){
        this->nonBlockingTimer.setInterval(100);
        this->blockingTimer.setInterval(100);

        connect(&this->blockingTimer, &QTimer::timeout, receiver, &TestReceiver::blockingSlot);
        connect(&this->nonBlockingTimer, &QTimer::timeout, receiver, &TestReceiver::nonBlockingSlot, Qt::DirectConnection);
        this->nonBlockingTimer.start();
        this->blockingTimer.start();
    }
private:
    QTimer nonBlockingTimer;
    QTimer blockingTimer;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    TestReceiver TestReceiverInstance;
    TestSender testSenderInstance(&TestReceiverInstance);
    QThread receiverThread;
    TestReceiverInstance.moveToThread(&receiverThread);
    receiverThread.start();

    return a.exec();
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow