PDA

Ver la Versión Completa : Problema: Hilo No ejecuta Procedimiento de su formulario.


aoshishin1
09-07-2012, 18:37:27
Buenos dias, es la primera ves que posteo aqui ya que hace poco eh empezado a usar delphi y la verdad esta comunicadad me ha salvado mucho al vida.

Bueno, resulta que me he topado con el siguiente problema.

Tengo un proyecto en delphi el cual tengo un formulario de tipo MDIForm, el cual abro una ventana llamada FrmAuxialiar de tipo medichild (hija del otro formulario).

Dentro de esta ventana hija tengo creado un hilo, lo que quiero hacer es ejecutar dentro de este hilo un procedimiento declarado dentro de mi FrmAuxiliar, el problema es que cuando hago el excute, no me toma ese procedimiento, no lo reconoce, es como si el hilo no supiera donde se encuentra declarado o parado por asi decirlo.

Me gustaria saber uan forma de poder llamar a estos procedimientos dentro de mi hilo, para asi poder hacer esta multitarea,les muestro el codigo.


unit UTFrmAuxialiar;

interface

uses


type
THilo = class(TThread)
Lista: TListBox;
procedure Execute; override;
procedure MostrarContador;
procedure Terminar;
end;

private
Hilo : Thilo;



//------------------------------------------------------------------------------
procedure THilo.Execute;
var
i : integer;
begin
inherited;
FreeOnTerminate := True;
while not terminated do
begin
FrmAuxialiar.MostrarCargando;
end;
end;

procedure THilo.MostrarContador;
begin
FrmAuxialiar.MostrarCargando;
end;

procedure THilo.Terminar;
begin
FrmAuxialiar.OcultarCargando;
Terminate;
end;
//---------------------------------------------------------
procedure TFrmAuxialiar.MostrarCargando;
begin
Panel20.Visible:=true;
AdvCircularProgress1.Enabled := true;
end;

procedure TFrmAuxialiar.Nuevo1Click(Sender: TObject);
begin
hilo:=Thilo.Create(False);
hilo.Resume;
end;

Como veran, cuando hagvo el execute, me deberia de mostrar un panel y un circularbar, pero no lo hace.
Desde ya muchas gracias y espero que me brinde una pequeña ayuda.
Saludos!!

escafandra
09-07-2012, 20:14:51
Estudia el metodo Synchronize en la ayuda de delphi.

Saludos.

aoshishin1
09-07-2012, 23:43:28
Muchas gracias por tu respuesta, ya supe cual fue el error, ahorra miduda es al siguiente, me gustaria saber que tanta versatibilidad tiene un hilo para correr en segundo plano un procedimiento que no es propio de el, pro ejemplo.



procedure THilo.Execute;
var i : integer;
begin
inherited;
FreeOnTerminate := True;
while not terminated do
begin
Synchronize(MostrarContador);
end;
end;

procedure THilo.MostrarContador;
begin
FrmAuxialiar.MostrarCargando;
end;

procedure TFrmAuxialiar.MostrarCargando;
var
i:integer;
begin
i:=1;
While i>0 do
begin
i:=i+1;
end;
end;


Estoy forzando a un bucle infinito, y quiero ver si se respeta la concurrencia, pero al hacer esto se me traba la pantalla.
Me gustaria saber el por que, y si hay alguna manera que el procedimiento "Mostrarcargando" se pueda correr paralelamente sin definirlo dentro del hilo.

Muchas gracias!!!!!

escafandra
10-07-2012, 08:09:23
No olvides poner las etiquetas de código para que éste sea legible.

Lo que bloquea tu APP es FrmAuxialiar pues éste bloquea los mensajes de la App.

Mira esto:


procedure THilo.Execute;
begin
FreeOnTerminate := True;
while not terminated do
Synchronize(FrmAuxialiar.MostrarCargando);
end;

procedure TFrmAuxialiar.MostrarCargando;
var
i:integer;
begin
i:=1;
Show;
While i>0 do
begin
Application.ProcessMessages;
i:=i+1;
end;
end;


Este ejemplo es un tanto absurdo pues el bucle del thread llama repetidamente a un método de un formulario que presenta un bucle infinito con lo que el bucle del Thread se ejecuta sólo una vez...

El método Execute del thread no tiene porqué tener un bucle, en ese caso termina cuando termine Exectue. Tu decides lo que tiene que hacer.


Saludos.

aoshishin1
10-07-2012, 16:21:14
Buenos dias, Escafranda mcuhas gracias por aclararmelas varias dudas con tu comentario, ahora me gustaria saber las dos cosas siguientes si eres tan amable:

1- Un hilo termina cuando termina de ejectar el execute?, o cuando ejecuto el terminate?

2- El objetivo mio era que el codigo del Frmuxiliar.mostrarcargando se corriera en segundo plano de manera que no haga trabar la ventana, perocomo este es propio del formulario no se si habra alguna forma de hacer eso, de llamar ese procedimiento y se ejecute en segundo plano sin que me haga trabar la pantalla.

Espero su pronta respuesta y muchas gracias!!

escafandra
10-07-2012, 18:47:49
Un hilo termina cuando termina su bucle principal. Si miras el ejempo que te puse, ya no se traba al añadir Application.ProcessMessages;

Si no quieres que aparezca ningún formulario, creo que es mas lógico que no uses uno sino que tu función pertenezca al thread.

Saludos.

escafandra
10-07-2012, 20:01:25
2- El objetivo mio era que el codigo del Frmuxiliar.mostrarcargando se corriera en segundo plano de manera que no haga trabar la ventana, perocomo este es propio del formulario no se si habra alguna forma de hacer eso, de llamar ese procedimiento y se ejecute en segundo plano sin que me haga trabar la pantalla.

Si lo que quieres es no acceder a ningún elemento visual del FrmAuxialiar, ningún componente de la VCL existente en él desde el Thread, entonces no te hace falta usar Synchronize. Lee en la ayuda de delphi su razón de ser. En ese caso, y al no usar Synchronize, tampoco será necesario el uso de ProcessMessages y el código funciona bien así:


procedure THilo.Execute;
begin
FreeOnTerminate := True;
while not terminated do
FrmAuxialiar.MostrarCargando;
end;

procedure TFrmAuxialiar.MostrarCargando;
var
i:integer;
begin
i:=1;
While i>0 do
i:=i+1;
end;

Ahora lo que tienes que ver es que es lo que quieres que tu código haga.


Saludos.

Chris
10-07-2012, 21:37:57
Una pregunta: ¿Pará qué utilizas un segundo hilo sólo para mostrar un panel? Mostrar un panel toma un par de milisegundos. Un tiempo invisible al usuario. Si mostrar el panel es el único propósito del hilo, te estás complicando la vida.

Si hicieras cálculos complicados que toman más de un segundo en procesarse, un hilo independiente sería una buena idea. Pero en este caso no le encuentro el sentido.

Aparte, a cómo lo estás haciendo ahora, estás introduciendo bugs en tu aplicación. En tu código veo líneas propicias a EAccessViolation.

escafandra
11-07-2012, 00:10:47
Yo creo que hasta ahora son meras pruebas de funcionamiento. El propósito final no está claro...

Saludos.

Al González
11-07-2012, 02:27:22
Hola, sólo añadir para aoshishin1 (¡salud!), que la funcionalidad de Synchronize es semejante a la del evento OnIdle de la aplicación (o de un objeto TApplicationEvents), es decir, el código de interés es ejecutado por el hilo principal de la aplicación (como si el hilo alterno no existiese).

Synchronize tiene mayor utilidad cuando el método Execute del nuevo hilo realiza otras tareas en verdadero segundo plano. Así, las tareas que pueden no ser seguras para hilos (thread-safe) se delegan al hilo principal a través de método Synchronize. Básicamente, las tareas no seguras para hilos son aquellas que afectan a regiones de memoria que varios hilos comparten, como puede ser cambiar o destruir un objeto al que instantes después otro hilo (como el principal) intentaría acceder.

Por otra parte, aunque sea algo sobrado para lo que busca aoshishin1, cabe mencionar que como alternativa a Synchronize está el uso de secciones críticas (http://es.wikipedia.org/wiki/Secci%C3%B3n_cr%C3%ADtica).

Saludos cordiales. :)