Поиск…


Использование Qt: DirectConnection, когда объект приемника не получает сигнал

Несколько раз вы видите, что в потоке отправителя излучается сигнал, но подключенный слот не вызывается (другими словами, он не получает сигнал), вы спросили об этом и, наконец, выяснили, что тип соединения Qt :: DirectConnection исправит его, поэтому проблема найдена и все в порядке.

Но, вообще говоря, это плохая идея использовать Qt: DirectConnection, пока вы действительно не знаете, что это такое, и нет другого пути. Давайте объясним это больше. Каждый поток, созданный Qt (включая основной поток и новые потоки, созданные QThread), имеет цикл событий, цикл событий отвечает за прием сигналов и вызывает aproporiate слоты в потоке. Генерирование, выполняющее операцию блокировки внутри слота, является плохой практикой, поскольку оно блокирует цикл событий этих потоков, поэтому никакие другие слоты не будут вызваны.

Если вы блокируете цикл событий (делая много времени или блокируя операцию), вы не будете получать события в этом потоке, пока цикл события не будет разблокирован. Если операция блокировки блокирует цикл события навсегда (например, занято во время), слоты никогда не могут быть вызваны.

В этой ситуации вы можете установить тип подключения для подключения к Qt :: DirectConnection, теперь слоты будут вызываться, даже если цикл событий заблокирован. так как это может сломать все? В Qt :: DirectConnection Slots будут вызываться в потоках эмиттеров, а не потоках приемников, и он может сломать синхронизацию данных и столкнуться с другими проблемами. Поэтому никогда не используйте Qt :: DirectConnection, если вы не знаете, что делаете. Если ваша проблема будет решена с помощью Qt :: DirectConnection, вы должны тщательно изучить ваш код и выяснить, почему ваш цикл событий заблокирован. Не очень хорошая идея заблокировать цикл событий и его нельзя рекомендовать в Qt.

Вот небольшой пример, который показывает проблему, так как вы можете видеть, что nonBlockingSlot будет вызываться даже блокировкой блокировки блокировки блокировки с while (1), которая указывает на плохое кодирование

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow