Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Ejecutar form en un hilo (https://www.clubdelphi.com/foros/showthread.php?t=89626)

turbopascual5.0 29-12-2015 13:34:18

Ejecutar form en un hilo
 
Hola a todos.
Estoy con una aplicación en la que en el evento on show de un form realizo varias tareas de manejo de un cubo olap, accesos varios a tablas sql, actualización de tablas, etc. Es un proceso lento, tarda unos 30 segundos. Así que creé un form con un label y una imagen giff animada, el típico calculando con un circulo animado.
Tirado del foro (que me es de una ayuda inestimable) configuré el form para que se mantenga en primer plano, no tenga botones de minimizar, etc.
y en el evento on show implementé:
Código Delphi [-]
form23.show;  //.....todo el código de accesos y cálculos   form23.close;
El programa funciona bien, pero el giff animado se queda congelado. El form se crea al arrancar el programa, también probé a crearlo en tiempo de ejecución, pero el giff se sigue quedando congelado. Para comprobar que no era cuestión de un fallo del contenedor del giff asigne en el form principal un botón para mostrarlo, y entonces sí que la imagen está animada.
Tambien he probado con insertar varios Application.ProcessMessages() en el código de acceso a bases, cálculos, etc ....... y nada, congelado.
Como había leído algo de los hilos de ejecución me he planteado crear un hilo solo para ejecutar el form
He implementado el siguiente código en el form resultados (en el evento onshow) (primero presento el form de espera, hago los cálculos, y cierro el form de espera)
Código Delphi [-]
type    
  THilo = class( TThread ) 
  private protected procedure Execute; override; 
  procedure terminarlo; 
end;   
TForm14 = class(TForm)     
ADOQuery1: TADOQuery;  
DataSource1: TDataSource;     
ADOQuery2: TADOQuery; 
DataSource2: TDataSource; // siguen todos los componentes de form14, corto aquí para abreviar.
y además
Código Delphi [-]
var   
Form14: TForm14;  
pendiente,anticipos, periodificaciones:real;      
Dia, Mes, Año : Word;  
Hoy,fechamala: TDateTime;  
miaño:string;    
X,TOTEM:integer;    
pasoactual:string;  
hilo:thilo;   
implementation  
uses  currando;  // (es el form23)  {$R *.dfm}    
procedure thilo.Execute;  
begin  
  inherited;  
  Synchronize(form23.show);  
  Application.ProcessMessages();  
end;   
procedure Thilo.Terminarlo; 
begin   
  Synchronize(form23.close);    
  Terminate; 
end;
y en el evento on show
Código Delphi [-]
procedure TForm14.FormShow(Sender: TObject);
var x:integer; 
begin
  hilo := Thilo.Create(true); 
  Hilo.Priority := tpTimeCritical;   
  hilo.Resume;
  Application.ProcessMessages();
  // toda el código de acceso a bases de datos, etc 
  hilo.terminarlo(); 
  FreeAndNil( Hilo );
end; // final del procedure
El form de espera aparece, los cálculos se hacen, el form se cierra..... todo bien, pero el giff sigue congelado.
Es como si el hilo de ejecución de la presentación del form no "chupase" cpu (o al menos eso pienso),
Gracias a todos de antemano por vuestro tiempo, y disculpas si hay alguna metedura de pata grande, solo programo por afición.

AgustinOrtu 29-12-2015 16:11:58

Yo mejor mandaría todo ese código del evento OnShow al hilo; entonces, creas el form con el gif, creas el hilo y que ejecute su trabajo. Cuando termina, creas el form principal y cierras el del gif

El trabajo pesado no debe hacerse en los form, que son elementos para representar estados y datos, nada más.

El trabajo pesado se debe hacer lo más lejos posible del form, de esta manera te es más fácil refactorizar el código y no queda fuertemente acoplado. Con el tiempo da sus frutos

turbopascual5.0 29-12-2015 17:52:27

Cita:

Empezado por AgustinOrtu (Mensaje 500883)
Yo mejor mandaría todo ese código del evento OnShow al hilo; entonces, creas el form con el gif, creas el hilo y que ejecute su trabajo. Cuando termina, creas el form principal y cierras el del gif

El trabajo pesado no debe hacerse en los form, que son elementos para representar estados y datos, nada más.

El trabajo pesado se debe hacer lo más lejos posible del form, de esta manera te es más fácil refactorizar el código y no queda fuertemente acoplado. Con el tiempo da sus frutos


Gracias por tu respuesta.

La verdad es que tambien me habia planteado esa opción.

Pero aquí ya me doy de bruces con mi ignorancia.

Supongo que el código lo he de poner en :

Código Delphi [-]
procedure thilo.Execute;
begin
  inherited;
 //aquí el código pesado
end;


El caso es que al colocarlo:

Por ejemplo pego un trozo del manejo de bases de datos

Código Delphi [-]
procedure thilo.Execute;
begin
  inherited;
cube2.active:=true;
 Hoy := Now;
  // Ahora extraemos los valores de "Hoy"
  DecodeDate(Hoy, Año, Mes, Dia);
 // Y a partir de ahora podemos manejar esos valores como queramos

// posicionamos el combobox en el año actual

miaño:=inttostr(año);
 for x:=0  to combobox2.items.Count do
   begin
   if combobox2.items[x]=miaño then
        totem:=x;
   end;

combobox2.ItemIndex:=totem;
adoquery1.Active:=true;
adoquery2.Active:=true;
adoquery9.Active:=true;
adoquery11.Active:=true;
end;


Todos los componentes adoquery, el combobox y el cube me indica un error de undeclared Identifier. No los logra "ver", y no sé donde indicarlo. He leído que si manejo componentes externos al hilo les he de poner syncronize, aquí lo he obviado (tampoco poniendolo los ve).

Independientemente, la verdad, siendo que el hilo está forzado en prioridad al máximo....... el balanceo de carga deja mucho que desear (win xp, delphi 2009).

AgustinOrtu 29-12-2015 18:04:06

La parte de la fecha no deberia ser algo pesado, eso podria gestionarlo el form

El problema lo tenes en los query. Por que poner componentes query en un form? Lo de "identifier not declared" es porque justamente el hilo no conoce ninguna variable con ese nombre, estan en el form, que es otro objeto del cual el thread no sabe ni deberia saber

deliriun 31-12-2015 23:27:15

Tal vez si usas este método te ayude..

Código Delphi [-]
var
  Retorno: Cardinal;

procedure Ejecutar;
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end;

begin
      CreateThread(nil,0,Pointer(@Ejecutar),nil,0,Retorno);
 end;


Yo tenía un problema en la inyección de un Cheat a un juego, que se quedaba trabado el juego, y esto me ayudo a ver úsalo y nos dices ;)


La franja horaria es GMT +2. Ahora son las 06:03:21.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi