La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Desarrollador Profesional de Juegos Programación III Unidad II Una clase thread para window.

Presentaciones similares


Presentación del tema: "Desarrollador Profesional de Juegos Programación III Unidad II Una clase thread para window."— Transcripción de la presentación:

1 Desarrollador Profesional de Juegos Programación III Unidad II Una clase thread para window

2 Después de tratar todo el tema thread ya podemos utilizar las funciones que escribimos. Y para hacer nuestro código más limpio y más fácil de entender y programar, lo siguiente es crear una clase thread que debería simplificar la creación y el uso de hilos. Esto nos permitirá no tener que volver a escribir el mismo código una y otra vez por cada thread. En este ejemplo solamente la escribiremos en el archivo main.cpp para no tener que alternar entre la cabecera y archivos de código fuente. ¿Qué necesitamos entonces? Un threadProc, un handle thread, y alguna forma sencilla de iniciar y detener nuestro hilo.

3 Clase thread #include using namespace std; class CThread { protected: bool terminateThreadFlag; // Flag para parar la ejecucion del threadProc HANDLE threadHandle; // El handle de nuestro thread public: CThread(); // constructor para setear la clase correctamente void begin(); // arranca el thread y ejecuta threadProc void end(); // señal para detener el thread virtual void threadProc() = 0; // Haremos este método virtual para poder heredar nuevos threads con un nuevo // método. Servirá para tener que definir solamente este método para cualquier // nuevo hilo que tengamos que crear, y poder así usar los demás métodos sin // reescribirlos. };

4 Clase thread CThread::CThread() { terminateThreadFlag = false; // para indicar al thread que NO termine! threadHandle = NULL; // NULL al handle del thread } /* En las unidades anteriores vimos que los hilos realizaban un ciclo un número determinado de veces. En la práctica, por lo general queremos que nuestros hilos hagan algo hasta que le indiquemos que se detengan. Para esto vamos a usar el terminatethreadFlag. Haremos un ciclo en nuestro threadProc que revisará el flag y si es TRUE, va a salir del ciclo. Debería ser algo como esto: */ aSampleThreadProc () { while( terminateThreadFlag == false) { //hacer algo acá }

5 El método end es muy simple. Todo lo que necesitamos hacer es poner nuestra terminateThreadFlag en true y entonces el procedimiento en forma automática deberá salir al final de su ciclo de proceso. // setea el terminate flag y permite al threadProc terminar naturalmente void CThread::end() { terminateThreadFlag = true; // usaremos waitForSingleObject acá para esperar al thread terminar. WaitForSingleObject( threadHandle, INFINITE); } //Este método detendrá la llamada del thread hasta que este thread //termine su ejecucion. Clase thread

6 Mientras terminar un thread es simple comenzarlo no es tan fácil. Tenemos un pequeño problema. Windows no tiene a threadProc como método de su clase. Esto significa que Windows no permitirá a CThread::threadProc() ser un método que pasaremos a CreateThread(). Obviamente que es un problema desde que queremos crear la clase para tenerlo como miembro de ella. La solución es un pequeño truco para engañar a Windows para que lo ejecute. Creamos una función común C++ que aceptará un puntero a CThread como argumento y entonces podremos correr el threadProc. void WindowsThreadFunction( CThread* theThread) { // ejecuta el theadProc theThread->threadProc(); }

7 Clase thread Recordemos que en la unidad anterior pasamos una variable a threadProc en la función CreateThread. Acá haremos lo mismo. Solamente que en vez de pasarle la dirección de un entero, pasaremos un puntero al thread que queremos arrancar. void CThread::begin() { // creamos el thread notando que aparece "this" en el 4 parámetro. threadHandle = CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE) WindowsThreadFunction, this, NULL, NULL); } // Cuando llamemos a CThread.begin() creamos el thread que ejecutará WindowsThreadFunction que escribimos y este llamará a nuestro threadProc.

8 Ahora que tenemos todas las piezas ¿Cómo las utilizamos? Definiremos un hilo con un ThreadProc. Haremos algo simple, por ejemplo un hilo que imprima números hasta que le digamos que pare. class CPrintSomethingThread : public CThread { public: int numberToPrint; // el numero a imprimir void threadProc( ) { // nuestro threadProc cout << “comenzó el Thread\n"; // para saber cuando arranca numberToPrint = 0; // empieze a imprimir en 0 // hasta que le digamos que salga while (!terminateThreadFlag) { // imprime el numero y lo incrementa cout << numberToPrint++ << endl; // dormimos un poco para poder ver el thread trabajando Sleep(100); } cout << "Thread Exiting\n"; // para saber cuando terminó } };

9 Ahora que hemos definido nuestro hilo, lo pondremos a trabajar. Creamos un objeto hilo y le decimos que empiece. Si hacemos esto, el hilo imprimirá para siempre así que es mejor tener alguna forma de evitarlo. Dejaremos al hilo principal (recordemos que es main) esperar a que se presione el teclado, y una vez que se pulsa una tecla, le diremos el hilo que finalice. Si hicimos, todo correctamente el hilo principal debería parase en ese punto hasta que nuestro hilo termine de ejecutar. Luego se le permitirá continuar con el resto del programa. void main() { cout << “Ejemplo de una clase Thread “<<endl; CPrintSomethingThread theThread; // creamos un objeto thread theThread.begin(); // le decimos al thread que empiece cin.get(); // esperamos hasta que se presione una tecla theThread.end(); // entonces le indicamos al thread que pare system("pause"); // y esperamos al usuario que termine el programa }

10 Como vemos esta clase es simple de usar, y a partir de ella nunca tendremos que escribir CreateThread() de nuevo. Todo lo que tenemos que hacer es heredar un thread con un threadProc nuevo, llamar a begin() y nuestra clase hará todo el trabajo por nosotros. Esta forma de programar es fácil de usar y codifica al programa de forma tal, que otro programador pueda agregar o modificar cosas sin saber lo que está pasando (sobretodo cuando se trabaja en un proyecto con muchas personas). Por supuesto que se le podrían agregar más cosas a la clase para que sea más fácil de usar o más versátil. Recordemos que no hay una sola forma de programar, y los threads no son la excepción. Para probar podríamos hacer que threadProc no tenga un ciclo. Dejemos que la clase mantenga el ciclo, porque ¿que sucede si algún programador se olvidó de verificar el terminateThreadFlag y sale de su ciclo. No habría manera de terminar el hilo. Bueno, si el programador escribe una función que realiza un frame del ciclo del proceso, entonces podría mantener el ciclo oculto para él y comprobar el terminateflag por si mismo ¿no? Otra opción es no tener la threadProc como función virtual que hace que el programador deba derivar una nueva clase para cada subproceso que quiera crear, y pasar un puntero a una función en la función begin(). Si se elige este camino, nunca tendremos derivar un thread nuevo, simplemente asignar el thredProc y se dejarlo ejecutar. Las opciones son infinitas, lo importante es decidir que acceso deseamos que otros programadores tengan sobre el thread, y cómo deseamos que la clase se utilice.


Descargar ppt "Desarrollador Profesional de Juegos Programación III Unidad II Una clase thread para window."

Presentaciones similares


Anuncios Google