QtConcurrentRun - Haciendo aplicaciones con hilos en Qt4

Preámbulo:

En estos días me he visto en la tediosa necesidad de crear un hilo separado en Kata Kuntur para que al exportar a un gestor DBMS, como MySQL, no se quede "colgada" la aplicación. Cuando se tenía un diagrama con más de 30 entidades (Según lo que me comentó el Ing. Gothy Alvarón) se quedaba colgada la interfaz mientras se realizaba la exportación a dicho gestor de base de datos. La solución, tecnicamente hablando, era la de crear un hilo que se encargue de la exportación a la base de datos para que el hilo principal (llamado también hilo de GUI) quedara libre para renderizar los gráficos.

 

Tuve que leer toda la documentación de Qt con respecto a hilos, ademas de hechar una ojeada al código de dichas clases (lo sé soy muy curioso :P ), aunque mi primera idea era crear una clase heredada de QThread y realizar la operación de exportación en dicha clase, no quería hacerlo hasta que entendiera, por lo menos, el 60% de la documentación acerca de Threads de Qt. Al terminar de leer la respuesta fue más sencilla...... usar la función run del namespace QtConcurrent, no necesito crear una clase heredada de QThread, solo debo usar run jejejjejejej.

QtConcurrent::Run

Según la documentación de Qt, la función QtConcurrent::run() corre una función en un hilo(thread) separado, Si la función devuelve n valor éste puede ser manejado mediante las API QFuture.

Para poder usar este espacio de nombres (por lo menos la función run de QtConcurrent) debes incluir la cabecera:

#include <QtConcurrentRun>

Una vez incluida la cabecera, el uso es sencillisimo, Primero declaramos la función:

void exportar(QString server, QString password, QString baseDatos){
/*
Código personalizado aquí
*/
}

Ahora usamos QtConcurrent para llamar de manera asíncrona a nuestra función exportar:

QFuture future = QtConcurrent::run(exportar, QString("localhost"), QString("root"), QString("root"));

Y ¡listo!. Pero este caso sólo nos funcionará en programación secuencial, si queremos usarlo dentro de una clase (Mi caso :) ) tendriamos que cambiar alguna parte del argumento. Veámos primero la clase declarada:

class FormExportDBMS : public QWidget {
    Q_OBJECT
public:
	FormExportDBMS(QWidget *parent = 0);
	~FormExportDBMS();
	void exportar();
private slots:
	void on_pushButton_clicked();
};

La función exportar de la clase FormExportDBMS (que es una interfaz gráfica)es la que quiero ejecutar en un hilo aparte, ahora en el archivo .cpp implemento las funciones:

void
FormExportDBMS::on_pushButton_clicked()
{
	/*Aqui ejecutamos la función exportar desde QtConcurrent::run*/
	QtConcurrent::run(this,&FormExportDBMS::exportar);
}
void
FormExportDBMS::exportar(){
	/*Código borrado por razones obias :P*/
}

Donde simplemente this hace referencia a la misma clase y &FormExportDBMS::exportar es la declaración de la función exportar de la clase FrmExportDBMS. Fue muy fácil la implementación, no me domré ni 5 minutos, así que si tienes una ventana gráfica que se cuelca mientras intenta conectarse a la Base de Datos y realizar operaciones...... te recomiendo usar QtConcurrent::run.

Sistemas Operativos: 
Lenguaje de programación: