Publicado en The Cold Sun (http://www.thecoldsun.com) Inicio > PDF para impresora > PDF para impresora Programación multihilo en Delphi. TThread y sincronización básica Table of Contents [hide] Introducción Definiendo nuestro hilo Sincronización básica Nota: Introducción Si no lo has leido ya, y eres relativamente nuevo al mundo de la programación multihilo es recomendable empezar leyendo la Introducción a la programación multihilo [1] para poder decidir correctamente si realmente es necesario implementar un sistema multihilo o no. Definiendo nuestro hilo Delphi facilita mucho la creación de hilos de ejecución proporcionando una clase base que podemos heredar para definir nuestras tareas de ejecución. Esta clase es la clase TThread. Un ejemplo de una aplicación que usa una tarea para comprimir un archivo. Heredamos la clase TThread y definimos lolaque queremos que TMiThread = el hilo haga haciendo un override del metodo Execute } type FFileName :Execute; String; class(TThread) public {private El constructor de clase CreateSuspended : la Si se crea suspendida :TMyThread; El fichero el que se aplica tarea Create(CreateSuspended :TObject); boolean; }FileName FileName :class(TForm) string); c onstructor override; override; TForm1 =declarations end; BtnComprimir: TButton; BtnComprimirClick(Sender: procedure private thr2 :Create(CreateSuspended); Private declarations }la tarea public {thr1, Public }sobre TMiThread.Create(CreateSuspended boolean); constructor FFileName FileName; // Inicializar los que queramos inherited Execute; end; procedure begin El código que ejecutará lafichero tarea Por ejemplo comprimir el pasado TForm1.OnBtnComprimirClick(Sender :: TComponent); thr1 TMyThread.Create(true,"MiFichero.txt"); Creamos la tarea suspendida thr2 TMyThread.Create(true,"Otro.txt"); thr1.Resume; thr2.Resume; Iniciar las tareas thr1.Terminated thr1.WaitFor; // Esperar a= acaben thr2.Terminated thr2.WaitFor; if not= then end; En el código anterior podemos observar con que basta con crear una clase que herede de la clase TThread y realizar un override del metodo Execute poniendo en él el código que queramos que realice la tarea. Este código suele seguir generalmente este patron: Execute; {procedure algún proceso repetitivo hasta que laal tarea termine } while RealizarTrabajo; Self.Terminated dohilo irquiere begin FinalizarRecursos; end; // Esto puede aqui (si los recursos son privados) // Ejecutar o ennot el destructor (si otro acceder resultado) Cuando se llama al metodo Terminate de la clase TThread, el valor de Terminated se pone a true y la función Execute se sale. Aunque existen formas de "matar" hilos mediante el API de windows la forma más común (y más recomendable) de actuación es "solicitar" al hilo su terminación (generalmente desde el hilo principal) llamanda al metodo Terminate y después quedarse a la espera de que el hilo finalice (llamando al metodo WaitFor) De esta forma podemos ver que la creación de hilos en Delphi es una cosa muy sencilla y que, de forma rápida, podemos distrubir la carga de trabajo entre varias tareas. Sincronización básica Uno de las complicaciones de la programación multihilo es la problemática asociada al acceso simultaneo a las variables compartidas y la necesidad de sincronizar dichos accesos de forma que no haya conflictos. La problemática de los acceso a variables compartidas es un problema común proveniente de la necesidad de atomicidad en algunas operaciones. Por ejemplo, analizando la operación i := i + 1; que incrementa una variable global i en uno, (que por otro lado es uno de los ejemplos más típicos que se pueden poner) observamos que, si dos hilos de ejecucíón intentan ejecutar el código simultaneamente podría pasar que: Entra el hilo 1 y lee el valor de i, por ejemplo 7, (y lo almacena en un registro de máquina) Justo en ese momento se produce un cambio de contexto y entra a ejecutar el hilo 2 El hilo 2 lee el valor de i (7), le suma 1 y lo almacena Vuelve a entrar el hilo 1, recupera el valor del registro de la máquina (7), le suma 1 y lo almacena El resultado final obtenido será 8 cuando lo que esperariamos obtener si entrarán dos hilos cuando el valor es 7 sería 9. Una forma básica de solucionar este problema es utilizar el metodo Synchronize de la clase TThread. Dicho metodo produce la ejecución del metodo especificado desde el hilo de ejecución principal de forma que no haya conflictos. De esta forma la llamada anterior quedaría como: IncrementaI; iSelf.Synchronize(PulsaBoton); ipulso + 1; PulsaBoton; Button1.Click(); procedure begin end; ........... Código dedel .............................. Aqui incremento i ejecución Self.Synchronize(IncrementaI); //:= Y elTMyThread.Execute; boton formulario De esta forma evitamos cualquier tipo de problema en la sincronización de acceso a los recursos. Nota: Casi todos los componentes VCL de delphi (botones, formularios, treeviews, etc) no son ThreadSafe, es decir, no soportan ser invocados desde distintos hilos, por ello, toda llamada a algún metodo de un componente debe ser protegída mediante el metodo Synchronize. Tags: Delphi [2] Multihilo [3] Articulos [4] Enviado por Jorge el Mar, 12/09/2008 - 18:22. URL de Origen: http://www.thecoldsun.com/es/content/12-2008/programacion-multihilo-en-delphi-tthread-ysincronizacion-basica Enlaces: [1] http://www.thecoldsun.com/node/40 [2] http://www.thecoldsun.com/es/category/common/delphi [3] http://www.thecoldsun.com/es/category/tags/multihilo [4] http://www.thecoldsun.com/es/category/content/articulos