Qt
Errores comunes
Buscar..
Uso de Qt: DirectConnection cuando el objeto receptor no recibe señal
Algunas veces ves que se emite una señal en el subproceso del remitente pero la ranura conectada no llama (en otras palabras, no recibe señal), has preguntado al respecto y finalmente obtuviste el tipo de conexión Qt :: DirectConnection que lo solucionaría. Así que el problema encontrado y todo está bien.
Pero, en general, es una mala idea usar Qt: DirectConnection hasta que realmente sepa qué es esto y no haya otra manera. Expliquémoslo más. Cada subproceso creado por Qt (incluido el subproceso principal y los nuevos subprocesos creados por QThread) tiene un bucle de eventos, el bucle de eventos es responsable de recibir señales y llamar a ranuras apropiadas en su hilo. En general, la ejecución de una operación de bloqueo dentro de una ranura es una mala práctica, ya que bloquea el bucle de eventos de esos hilos para que no se llame a ninguna otra ranura.
Si bloquea un bucle de eventos (al realizar una operación que requiere mucho tiempo o bloqueo), no recibirá eventos en ese hilo hasta que se desbloquee el bucle de eventos. Si la operación de bloqueo bloquea el ciclo de eventos para siempre (por ejemplo, ocupado mientras está ocupado), las ranuras nunca podrían llamarse.
En esta situación, puede establecer el tipo de conexión en conectarse a Qt :: DirectConnection, ahora se llamarán las ranuras, incluso se bloquea el bucle de eventos. Entonces, ¿cómo esto podría hacer que todo se rompiera? En Qt :: DirectConnection, las ranuras se llamarán en subprocesos emiter, y no en subprocesos de receptor, ya que pueden interrumpir las sincronizaciones de datos y encontrar otros problemas. Nunca use Qt :: DirectConnection a menos que sepa qué está haciendo. Si su problema se resolverá mediante el uso de Qt :: DirectConnection, debe tener cuidado y observar su código y descubrir por qué se bloquea el bucle de eventos. No es una buena idea bloquear el bucle de eventos y no se recomienda en Qt.
Aquí hay un pequeño ejemplo que muestra el problema, ya que se puede ver que el bloqueo no bloqueado se llamaría incluso el bucle de evento bloqueado de bloqueo de ranura con while (1) que indica una codificación incorrecta
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();
}