c++ - Señales Qt(QueuedConnection y DirectConnection)
qthread qt-signals (3)
Estoy teniendo problemas con las señales Qt.
No entiendo cómo funcionan DirectConnection
y QueuedConnection
?
Estaría agradecido si alguien explicará cuándo usar cuál de estos (código de muestra sería apreciado).
La respuesta de Jacob es asombrosa. Me gustaría agregar un ejemplo comparativo a la Programación Embebida.
Procedente de un fondo RTOS / ISR incorporado, fue útil ver las similitudes en DirectConnection de Qt con el comportamiento preventivo de los ISR y la QueuedConnection de Qt con los mensajes en cola en un RTOS entre tareas.
Nota al pie: viniendo de un fondo incrustado, es difícil para mí no definir el comportamiento en la programación. Nunca dejo la discusión como Auto, pero eso es solo una opinión personal. Prefiero que todo se escriba explícitamente, y sí, eso se pone difícil a veces.
No verá mucha diferencia a menos que trabaje con objetos con afinidades de subprocesos diferentes. Digamos que tienes QObjects A
y B
y ambos están conectados a diferentes subprocesos. A
tiene una señal llamada somethingChanged()
y B
tiene una ranura llamada handleChange()
.
Si usas una conexión directa
connect( A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection );
el método handleChange()
realmente se ejecutará en el hilo de A
Básicamente, es como si emitir la señal llama al método de ranura "directamente". Si B::handleChange()
no es seguro para subprocesos, esto puede causar algunos errores (difíciles de localizar). Por lo menos, te estás perdiendo los beneficios del hilo adicional.
Si cambia el método de conexión a Qt::QueuedConnection
(o, en este caso, deje que Qt decida qué método usar), las cosas se vuelven más interesantes. Suponiendo que el hilo de B
está ejecutando un bucle de evento, emitir la señal publicará un evento en el bucle de evento de B
El bucle de evento pone en cola el evento y, finalmente, invoca el método de ranura cuando el control vuelve a él (es el bucle de evento). Esto hace que sea bastante fácil tratar con la comunicación entre subprocesos en Qt (nuevamente, suponiendo que los subprocesos ejecutan sus propios bucles de eventos locales). No tiene que preocuparse por los bloqueos, etc. porque el bucle de eventos serializa las invocaciones de las ranuras.
Nota: Si no sabe cómo modificar la afinidad de subprocesos de QObject, consulte QObject::moveToThread
. Eso debería hacerte comenzar.
Editar
Debería aclarar mi oración de apertura. Hace una diferencia si especifica una conexión en cola, incluso para dos objetos en el mismo subproceso. El evento aún se publica en el ciclo de eventos de la secuencia. Por lo tanto, la llamada al método sigue siendo asíncrona, lo que significa que puede retrasarse de maneras impredecibles (dependiendo de cualquier otro evento que el ciclo deba procesar). Sin embargo, si no especifica un método de conexión, el método directo se usa automáticamente para las conexiones entre objetos en la misma cadena (al menos está en Qt 4.8).
además de la respuesta de Jacob Robbins:
la afirmación "No verá mucha diferencia a menos que trabaje con objetos con afinidades de subprocesos diferentes" es incorrecta ;
emitir una señal a una conexión directa dentro del mismo subproceso ejecutará la ranura de inmediato, al igual que una llamada de función simple.
emitir una señal a una conexión en cola dentro del mismo hilo enrutará la llamada al ciclo de eventos de hilos, por lo que la ejecución siempre ocurrirá con retraso.
La clase basada en QObject tiene una conexión en cola a sí misma