Sök…


Använda Qt: DirectConnection när mottagarobjektet inte tar emot signal

Vissa gånger ser du att en signal sänds ut i avsändartråden men anslutet kortplats ringde inte (med andra ord får den ingen signal), du har frågat om det och slutligen fått att anslutningstypen Qt :: DirectConnection skulle fixa det, så problemet hittades och allt är ok.

Men i allmänhet är det dålig idé att använda Qt: DirectConnection tills du verkligen vet vad som är detta och det finns inget annat sätt. Låter förklara det mer. Varje tråd skapad av Qt (inklusive huvudtråd och nya trådar skapad av QThread) har händelsslinga, händelsslingan ansvarar för att ta emot signaler och anropa aproporiat-spår i sin tråd. Generellt att utföra en blockeringsoperation inuti en plats är dålig praxis, eftersom det blockerar händelsslingan för de trådarna så att inga andra kortplatser skulle kallas.

Om du blockerar en händelsslinga (genom att göra mycket tidskrävande eller blockera operation) får du inte händelser på den tråden förrän händelsslingan kommer att blockeras. Om blockeringsoperationen blockerar händelsslingan för alltid (t.ex. upptagen medan) kan kortplatserna aldrig kallas.

I den här situationen kan du ställa in anslutningstypen i anslutning till Qt :: DirectConnection, nu kommer platserna att kallas till och med händelsslingan är blockerad. så hur detta kunde göra bröt allt? I Qt :: DirectConnection kommer slots att anropas i emittertrådar, och inte mottagartrådar och det kan bryta datasynkroniseringar och stötte på andra problem. Så använd aldrig Qt :: DirectConnection såvida du inte vet vad du gör. Om ditt problem kommer att lösas med hjälp av Qt :: DirectConnection, måste du ta hand om din kod och ta reda på varför din event-loop är blockerad. Det är inte en bra idé att blockera händelseslingan och den rekommenderas inte i Qt.

Här är ett litet exempel som visar problemet, eftersom du kan se att nonBlockingSlot skulle kallas till och med blockingSlot blockerad händels loop med medan (1) vilket indikerar dålig kodning

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow