Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Desarrollo en Delphi para Android (https://www.clubdelphi.com/foros/forumdisplay.php?f=57)
-   -   Ejecución bloqueada. Hilos de ejecución (https://www.clubdelphi.com/foros/showthread.php?t=89087)

muli 24-09-2015 17:21:07

Ejecución bloqueada. Hilos de ejecución
 
Hola a todos. Tengo una aplicación en Android con xe6 que cuando abre una base de datos que tengo en la tarjeta microsd de la tablet, pasa un rato y parece que queda bloqueada, pero no lo está, intenté poner un aniIndicator para que mientras se abre el query y rellena un listview con los datos se mueva el circulito para que el usuario no crea que tiene la aplicación bloqueada. Estuve viendo en san google el asunto de los thread, pero no me aclaro mucho y la información es bastante escasa,alguna ayuda para que cuando le doy a query.open, aparezca el aniIndicator y se mueva hasta que el query finalice de traer los datos.

Saludos. a todos.

Neftali [Germán.Estévez] 25-09-2015 10:32:50

Échale un vistazo a este link.

muli 11-10-2015 12:33:01

No consigo que avance la barra de progreso.
 
Este es el código que uso después de visionar diferentes paginas de creación de threads, pero la barra de progreso no avanza, yo lo que quiero es que avance mientras no termina de abrirse la fuente de datos, para que el usuario no crea que la aplicación ha quedado colgada. También pensé en realizar el hilo con la fuente de datos, pero al terminar el hilo pierdo toda la referencia a los datos, por lo que no me sirve. Estoy trabajando con Delphi xe6 y para android. Si en lugar de una barra de progreso se tiene que hacer con una animación, me da igual, el caso es que la aplicación realice algo mientras abre los datos, tampoco son muchos registros, una vez abierta la fuente de datos se mueven perfectamente, incluso si hago un update de un registro es instantáneo.

Código Delphi [-]
// Declaro thread
THilo = class(TThread)
  Progreso: TProgressBar;
  procedure Execute; override;
  procedure ActualizarProgreso;
end;

  Hilo1: THilo; // variable global o pública
  Avance : Integer;

Implementation

procedure THilo.ActualizarProgreso;
begin
  Avance:=Avance+1;
  Progreso.Value:=Avance;
  if Avance>100 then
  Begin
    Avance:=0;
  End;
end;

procedure THilo.Execute;
begin
  inherited;
  FreeOnTerminate := True;
  while not Terminated do
  begin
    Synchronize(ActualizarProgreso);
  end;
end;

// Hasta aquí tengo los procedimientos del thread.
// Luego en el procedimiento de abrir los datos tengo esto.
Procedure TForm1.AbrirDatos.
Begin
    ProgressBar1.Value:=0;  // Inicio la barra de progreso.
    ProgressBar1.Visible:=True;
    Avance:=0;

    Hilo1 := THilo.Create(True);  // Creo hilo de ejecución.
    Hilo1.Progreso := ProgressBar1;
    Hilo1.Resume;
// Abro datos. Omito campos para hacerlo mas legible.
    Query1.Close;
    Query1.SQL.Clear;
    Query1.Connection:=FdConnection1;
    Query1.SQL.Add('Select *  From Registros Where Actual=0');
    Query1.SQL.Add('Order By Direccion');
    if not Query1.Prepared then Query1.Prepare;
    Query1.Open;
// Finalizo thread.
  Hilo1.Terminate;
  FreeAndNil( Hilo1 );

Neftali [Germán.Estévez] 11-10-2015 17:59:58

Así a primeras, lo que veo es que la variable avance, está definida fuera del thread y la estás utilizando dentro.
defínela dentro, pues no es necesarias fuera, o incluso elimínala, pues no la necesitas.

muli 12-10-2015 03:27:17

Nada amigo, elimino la variable avance y en su lugar pongo, pero la barra de progreso ni siquiera se mueve, incluso pasa una cosa curiosa en tiempo de diseño le tengo valor 80 para ver el color de la barra y no se lo quite, cuando inicio el procedimiento puedes ver que le paso el valor 0, y ni nada, no hace caso.

Código Delphi [-]
  Progreso.Value:=Progreso.Value+1;
  if Progreso.Value>100 then
  Begin
    Progreso.Value:=0;
  End;

mamcx 12-10-2015 04:08:30

Estas haciendo todo al revez.

La GUI corre en el thread principal y lo estas poniendo en un background. La parte "lenta" la estas dejando en el thread ppal, bloqueando la GUI.

No hay razon (normalmente) para poner GUI dentro de otro thread, siempre usa otros threads para correr de forma concurrente CPU/IO intensivo.

Por otro lado, si es solo poner un "espera mientras", entonces no tienes que hacer esto. Solo arranca el spinner al inicio, ejecuta la parte "lenta" y paras el spinner al final.

Porque ademas, ese progreso que tienes no sirve de nada...

Y estas masacrando la CPU al tener un while sin un respiro (un sleep o una tarea asincronica).

Y es mala cosa "matar" threads.

Mejor dicho, estudia mas sobre este tema ;)

muli 12-10-2015 11:45:47

No estoy haciendo ninguna espera, lo que quiero es que mientras el query trae los registros se mueva la barra de progreso, para que no parezca que la aplicación está congelada, o sea, que el usuario vea movimiento mientras se realiza la consulta.

Algún enlace entendible para estudiar más del tema. :):)

AgustinOrtu 12-10-2015 19:41:36

Revisa este post

mamcx 12-10-2015 19:43:05

Ya te explique el problema. Lee con cuidado.

Si simplementes copias/pegas un codigo por ahi sin entender como hacer multi-hilos terminaras sin querer incorporando bug(s) y/o haciendo el codigo mas ineficiente.

Un computador moderno (ie: De menos de 4 años para aca) es suficientemente rapido para hacer casi de todo en forma secuencial, y la mayoria de los lenguajes (como delphi) no son optimos para hacer concurrencia, asi que es facil hacer algo con problemas.

AgustinOrtu 12-10-2015 19:51:18

Estoy casi completamente de acuerdo

Digo casi porque para el caso de mostrar un "espere por favor" mientras se hace cierto procesamiento y no bloquear la UI es algo bastante sencillo en Delphi. Aunque admito que si hay que realizar calculos en paralelo y sincronizacion con Delphi es bastante mas complicado

NicolasP 28-11-2016 15:16:03

AniIndicator con Android
 
Tema viejo , pero hago un aporte. Después de buscar y leer por varios días post que dicen "lea este post..." lo pude hacer funcionar el AniIndicator para que se "mueva" con un proceso.
Me funciona en windows y también en Android 6.0 con D X7

Form Principal.
Código Delphi [-]
procedure TFmMAin.SB_DbReadClick(Sender: Tobject);

begin

 PAnelAviso.Visible := true;
 AniIndicator1.Enabled := true;
 Hilo := THilo.Create(True);
 Hilo.Start;
 while not Hilo.Finished do
  begin
   ProgressBar1.value := ProgressBar1.Value +1;
   sleep(20);
   if ProgressBar1.Value = 100 then
     ProgressBar1.Value := 0;
     Application.ProcessMessages;
  end;
 ProgressBar1.Value := 0;
 AniIndicator1.Enabled := false;
 PAnelAviso.Visible := false;

.....

Nota: El AniIndicator esta en un Panel. Le puse también un Progressbar para ver si funcionaban juntos. y funcionan!. Sin en el Application.ProcessMessages no funcionan.


Unidad para el proceso

Código Delphi [-]
unit procesos;

interface
uses
Classes, SysUtils;

type
  THilo = class(TThread)
  protected
  procedure Execute; override;
end;


implementation
 uses main;

procedure THilo.Execute;
begin
  FmMain.RestRequest1.Execute;
end;

end.


No se si es eficiente, pero no me importa. Lo importante que el usuario crea que lo es (ja) . Y vea que su dispositivo esta "pensando" ... después le podemos echar la culpa a las comunicaciones, etc....
:D


La franja horaria es GMT +2. Ahora son las 19:01:58.

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