Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 18-11-2005
manuel_conde manuel_conde is offline
Registrado
 
Registrado: nov 2005
Posts: 3
Poder: 0
manuel_conde Va por buen camino
Procesos largos, Threads y progreso

Hola a todos. Hoy os propongo un desafío que llevo tiempo encima de él.
El caso es que tengo unos eventos que hacen mogollón de cosas.
Por ejemplo, le doy a un botón de "Actualizar" y el evento hace cosas que pueden llevar unos veinte segundos. Entonces, mientras se realiza el proceso, me gustaría abrir un formulario con una label a modo de contador que fuese indicando el tiempo va transcurriendo.
Se me ocurrió lanzar un thread al inicio de la gestión del evento que abra un formulario y vaya actualizando la label, y matar el thread al final del proceso, pero ... oohhhh, el thread no hace nada hasta que termina todo el proceso.
Me gustaría saber si alguien ha resuelto algo así...
Por ejemplo:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
   th := tmythread.create(false); //creo el thread
   // Aquí va un proceso que le lleva 20 segs....
   // supongamos que en vez de llevarle 20 segs le lleva mucho, mucho tiempo:
   while true do begin end; 
 
   th.terminate; // terminamos el thread
end;

Mientras tanto... el thread estaría haciendo:
procedure TmyThread.Execute;
begin
 while not fin do
     Synchronize(UpdateCaption)
end;
 
procedure TmyThread.UpdateCaption;
begin
    Form1.Caption := floattostr(now);;
end;

---------------------------------------------
Lo que he visto es que el thread no empieza a funcionar hasta que termine el evento desde el cual se inició la ejecución del evento (y claro... empieza a funcionar caundo ya no hace falta).

Gracias a todos.

Última edición por vtdeleon fecha: 18-11-2005 a las 21:33:33. Razón: Etiqueta Delphi
Responder Con Cita
  #2  
Antiguo 19-11-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

He estado haciendo unas pruebas y lo que parece que puede ocurrir es que el hilo principal de la aplicación impida que el hilo que tú creas trabaje. Si dentro del proceso que te lleva tanto tiempo incluyeras un "Application.ProcessMessages;" verías cómo el hilo que creas realiza su función. De todos modos, no creo que fuera una buena idea.

Yo lo que pienso es que acaso no te sea necesaria la utilización de ningún hilo aparte del principal, y, mucho menos, utilizar ese hilo únicamente para mantener al usuario informado de cierto proceso que llevas a cabo... en el hilo principal.


Piensa que una aplicación no funciona mejor porque haga uso de dos o más hilos; es posible que sea al contrario. Los dos hilos no se ejecutarán en paralelo, de tal forma que cuando uno de ellos se ejecute el otro estará esperando "su turno", esperándose mutuamente de forma que acaso la tarea por esto mismo se retarde más de la cuenta.

Según he leído un proceso de diez segundos no implica la necesidad de mostrar cierto mensaje al usuario informándole del mismo: bastaría con el cambio del cursor del ratón: con el reloj de arena el usuario sabría que algo está llevándose a cabo.

Tratándose de veinte segundos, tal vez con un mensaje informativo que contuviera una imagen animada indicando que se está llevando a cabo una tarea fuera más que suficiente. Y, en todo caso, si es posible "medir" el proceso y mostrarle al usuario cierta información sobre su progreso,... en tu caso creo que podrías hacerlo en el mismo proceso. Si se trata de un bucle, por ejemplo, una de las instrucciones que incluya puede ser precisamente la que actualize determinada "Caption", "ProgressBar", etc.

En definitiva. El problema que te encuentras creo que estriba en que tratas de hacer uso de un dos hilos de ejecución cuando acaso no son necesarios, de tal forma que, efectivamente, la posible solución te ocasiona encima quebraderos de cabeza. En fin. No sé si todo este rollo te servirá de algo o no.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #3  
Antiguo 19-11-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola de nuevo,

Se me han pasado por alto un par de cuestiones. Primeramente darte la bienvenida a estos Foros y recomendarte (si me lo permites) la lectura de su guía de estilo. En segundo lugar te propongo una prueba. A la siguiente línea:

Código Delphi [-]
th := tmythread.create(false); //creo el thread
Añade esta otra:

Código Delphi [-]
th.Priority := tpHighest; // Prioridad para el thread
De tal forma que "la cosa" quede en:

Código Delphi [-]
th := tmythread.create(false); //creo el thread
th.Priority := tpHighest; // Prioridad para el thread
Si tienes un ordenador/computador más o menos como el mío podrás ver cómo ahora no es el hilo principal el que inutiliza al hilo que tú creas, sino al contrario: es el hilo que tú creas el que inutiliza al hilo principal... cosas de los Hilos.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #4  
Antiguo 19-11-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
Hola.

Aqui el problema del "congelamiento" del segundo hilo está en la llamada a Synchronize:

Cita:
Empezado por delphi help
Synchronize causes the call specified by Method to be executed using the main thread, thereby avoiding multi-thread conflicts. If you are unsure whether a method call is thread-safe, call it from within the Synchronize method to ensure that it executes in the main thread.
El punto es que para actualizar la etiqueta no hay de otra... debe hacerse en el hilo principal o habrá problemas.

Me parece mas lógico crear un segundo hilo para realizar el proceso en cuestión, mientras el hilo principal de la aplicación se queda en un ciclo informando al usuario del avance. Así, todo lo relacionado con la interfaz visual permanece en el hilo principal y se evita por completo el uso de Synchronize.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #5  
Antiguo 19-11-2005
manuel_conde manuel_conde is offline
Registrado
 
Registrado: nov 2005
Posts: 3
Poder: 0
manuel_conde Va por buen camino
Agradezco vuestras rápidas contestaciones.
He estado probando lo que me habeis recomendado:
1.- El cambio de la prioridad a tpHighest del nuevo thread no ha dado resultado, pues sigue congelado (incluso con time critical).
2.-La alternativa dada por jachguate tampoco me satisface del todo, porque lo que realmente tengo no es un proceso que tarde mucho, sino muchos procesos distintos. Aunque probaré la opción de crear un thread y pasarle la dirección del proceso a realizar (lo probaré hoy por la tarde y ya os comentaré), llevando a cabo el informe de estado en el thread principal.
3.- Probaré también la opción de cambiar el cursor del ratón, a ver qué tal.

Finalmente, he estado leyendo la guia de estilo (claro que te permito la recomendación).

Muchas gracias a todos. Nunca pensé tener respuestas tan rápido.
Un saludo a todos.
Responder Con Cita
  #6  
Antiguo 19-11-2005
manuel_conde manuel_conde is offline
Registrado
 
Registrado: nov 2005
Posts: 3
Poder: 0
manuel_conde Va por buen camino
Hola de nuevo a todos.

Ya he probado una alternativa: he creado un thread al cual se le puede pasar la dirección del trabajo a realizar, dejando para el proceso principal el trabajo de indicar el estado de progreso. Ahí va la solución:


Proceso principal:
Código Delphi [-]
type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
private
public
procedure ProcesoLargo1(datos : integer);
procedure ProcesoLargo2(datos : integer);
end;
var
Form1: TForm1;
implementation
uses unit2;
{$R *.dfm}
procedure tform1.ProcesoLargo1(datos : integer);
begin
// un proceso largo, y que tiene interacción con elementos
// visuales.
sleep(10000);
button1.Caption := inttostr(datos);
sleep(10000);
end;
procedure tform1.ProcesoLargo2(datos : integer);
begin
// un proceso largo, y que tiene interacción con elementos
// visuales.
sleep(10000);
button1.Caption := inttostr(datos);
sleep(10000);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
th : tmythread;
begin
th := tmythread.create(true);
th.ExecTrabajo(form1.ProcesoLargo1,1234);
while th.trabajando do
begin
application.ProcessMessages;
form1.Caption := 'Trabajando ' +floattostr(now);
end;
form1.Caption := 'Trabajo finalizado';
freeAndNil(th);
end;
Proceso del thread:
Código Delphi [-]
type
TCProcedure = procedure (datos: integer) of object; // Procedure in a class
tmythread = class(TThread)
public
trabajando : boolean;
procedure ExecTrabajo(proc : TcProcedure; losDatos: integer);
protected
datos : integer;
proceso : TcProcedure;
procedure Execute; override;
end;
implementation
procedure tmythread.ExecTrabajo(proc : TcProcedure; losDatos: integer);
begin
trabajando := true;
proceso := proc;
datos := losDatos;
resume;
end;
procedure tmythread.Execute;
begin
proceso(datos); // ejecuta el procedimiento de la otra clase
trabajando :=false;
end;

Seguiremos investigando....

Última edición por manuel_conde fecha: 19-11-2005 a las 18:27:22. Razón: ¡¡Encerrad el código fuente entre las etiquetas [DELPHI] ... [/DELPHI]!!
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 08:31:29.


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
Copyright 1996-2007 Club Delphi