Coloured Thread — Philippa Willitts, License CC-BY-NC-2.0

Hilos de trabajo usando señales y slots en Qt

Jesús Torres
Jesús Torres
Published in
3 min readFeb 18, 2013

--

Puedes leer la última versión actualizada y corregida del artículo original en mi sitio web: jesustorres.es.

Qt proporciona clases para hilos y mecanismos de sincronización que facilitan sacar las tareas de larga duración del hilo principal de la aplicación, lo que de lo contrario bloquearía la interfaz de usuario.

Una forma práctica de hacerlo la hemos visto anteriormente utilizando un buffer compartido. Sin embargo Qt provee a cada hilo de una cola de mensajes, lo que permite enviar señales a slots en otros hilos. Esto nos proporciona una forma sencilla de pasar datos entre los hilos de la aplicación.

Si no se indica lo contrario, las señales emitidas desde un hilo a un objeto en el mismo hilo son entregadas directamente. Es decir, que al emitir la señal se invoca el slot como si de un método convencional se tratara. Sin embargo si el emisor y el receptor residen en hilos diferentes, la señal es insertada en la cola de mensajes del hilo del objeto de destino. Así el slot correspondiente será invocado en el hilo receptor desde su bucle de mensajes.

En la actualidad esta es la forma recomendada de usar hilos en Qt ya que permite evitar el uso de de mecanismos de sincronización como QMutex, QWaitCondition, etc.

El ejemplo. Ordenar números enteros

El ejemplo que vamos a seguir básicamente consiste en ordenar un vector de enteros en un hilo de trabajo distinto al hilo principal.

Como se puede observar en la figura utilizaremos dos objetos, uno vinculado al hilo principal (clase Sorter) y otro al hilo de trabajo (clase SorterWorker). En una aplicación gráfica convencional con Qt la clase Sorter podría ser una ventana o cualquier otro control que quiera ceder una tarea al hilo de trabajo. Aquí no lo haremos así para que el ejemplo sea lo más sencillo posible.

Ejemplo de comunicación entre hilos en Qt

En Qt un objeto se dice que vive en el hilo en el que es creado. Esto se puede cambiar utilizando el método moveToThread() que tienen todas las clases de Qt que heredan de la clase base QObject.

La clase Sorter

La propia clase Sorter se hará cargo de crear el hilo de trabajo, que por defecto lo único que hace es iterar en su propio bucle de mensajes. Todos los detalles acerca de la creación de hilos ya los vimos anteriormente

La clase Sorter provee un método sortAsync() que podrá ser llamado por los clientes para ordenar un vector de números enteros. Puesto que la operación es asíncrona, necesitamos definir un slot vectorSorted() para ser notificados cuando el ordenamiento haya finalizado con éxito.

La implementación de esta clase sería la siguiente:

Como se puede observar, en el constructor de Sorter se usa el método qRegisterMetaType(), antes de conectar las señales, para registrar el tipo QVector<int>. Esto debe hacerse porque cuando una señal es encolada sus parámetros deben ser de tipos conocidos para Qt, de forma que pueda almacenar los argumentos en la cola.

Por otro lado en el destructor de Sorter tenemos cuidado de detener el hilo de trabajo en condiciones seguras cuando ya no va a ser necesario. Si no lo hacemos así, el hilo podría ser destruido por el sistema operativo en cualquier punto de la secuencia de instrucciones al termina la aplicación, lo que podría dejar los datos en uso en un estado indeterminado.

La clase SorterWorker

Como usar el ejemplo

Para usar el ejemplo sólo necesitamos crear una instancia de Sorter y llamar a su método sortAsync() para pedir que ordene el vector especificado.

Referencias

--

--

Jesús Torres
Jesús Torres

Docente e Investigador de la Universidad de La Laguna.