Programación multihilo en Delphi. TThread y

Anuncio
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
Descargar