Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 08-02-2011
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 22
gluglu Va por buen camino
Problemas con Threads

Hola a tod@s !

Necesito de nuevo acudir a vuestros sabios consejos para solucionar el siguiente asunto :

Tengo la posibilidad de crear varias instancias de un mismo Formulario. En este caso se trata de elaborar unos listados. Para ello en el Formulario Principal tengo creado
Código Delphi [-]
Arr_List : Array of TList_General;
siendo TList_General del tipo de mi formulario para listados.

A su vez, en cada formulario de listados necesito realizar una serie de cálculos adicionales los cuales he metido en un Thread, que se crea en cada una de las instancias de cada formulario de listado.

Me acabo de dar cuenta que (supongo que ahí está el fallo), el Thread creado en cada formulario tiene el nombre Calculate_Total, y por lo tanto cuando tengo dos instancias de formularios de listados, al terminar el thread Calculate_Total del primer formulario, también se para el Calculate_Total del segundo formulario de listados. .... claro, no están diferenciados por nombre.

Cómo soluciono este problema ? Tengo que crear igualmente un 'Array of TThread' ? Es eso factible ? Si es así, donde tengo que declarar ese Array, en el formulario principal ?

Antes de probar y meterme en estos líos, os quería preguntar y pedir consejo.

Gracias como siempre.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #2  
Antiguo 08-02-2011
Delfino Delfino is offline
Miembro
 
Registrado: jul 2003
Ubicación: Madrid
Posts: 974
Poder: 22
Delfino Va por buen camino
Tienes que llamar a cada metodo o thread del form con el prefijo Self, para q actue sobre esa instancia del form, suponiendo q para cada form le creas su thread especifico..
__________________
¿Microsoft? No, gracias..
Responder Con Cita
  #3  
Antiguo 08-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.440
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por gluglu Ver Mensaje
Me acabo de dar cuenta que (supongo que ahí está el fallo), el Thread creado en cada formulario tiene el nombre Calculate_Total, y por lo tanto cuando tengo dos instancias de formularios de listados, al terminar el thread Calculate_Total del primer formulario, también se para el Calculate_Total del segundo formulario de listados. .... claro, no están diferenciados por nombre.

Cómo soluciono este problema ? Tengo que crear igualmente un 'Array of TThread' ? Es eso factible ? Si es así, donde tengo que declarar ese Array, en el formulario principal ?
Lo lógico es que cada thread tenga como parámetro (o tenga acceso) al formulario al que pertenece. Para modificar la variable que corresponde a su formulario y no todos la del primero.

¿Cómo accedes a la variable Calculate_Total al acabar el thread? ¿Puedes poner el código?
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #4  
Antiguo 08-02-2011
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 22
gluglu Va por buen camino
Gracias por contestar.

Entiendo que un Thread es un 'ente autónomo' por lo tanto no sé si puedo utilizar Self en algún lado. Además después se juntaría con otro problema. En el propio Thread, a su vez se llama a otros procedimientos genéricos de cálculos, y en dichos procedimientos tengo que incrementar una variable del propio form o thread (según quien llame al procedimiento). Por lo tanto no veo cómo podría funcionar usando Self.

A Neftalí : Esa es precisamente la cuestión que se me presenta. Si el Thread es tal 'ente autónomo', cómo sé qué formulario creó un thread. Sí que es cierto que le podría pasar un parámetro o variable en la cual sepa qué form de listado lo ha llamado. Pero donde me dí cuenta del problema es que si ejecuto dos formularios de listados que a su vez cada uno llaman a un Thread que está declarado de la siguiente manera :

Código Delphi [-]
unit ListGeneral;
...
 
type
  TList_General = class(TForm)
....
 
  TCalculate_Total =  class(TThread)
    procedure UpdateMainForm;
  private
    ....
  public
    ....
  protected
    procedure Execute; override;
  end;
 
var
  List_General: TList_General;
  Calculate_Total: TCalculate_Total;

....
implementation
....

lo que tengo claro es que al definir mi Arr_List en el Mainfom como Array of TList_General, puedo acceder a cada instancia de Arr_List por su posición en el array, es decir, a cada form de listado por su posición en el Array Arr_List.

Pero cuando en Arr_List[0] (p.ej.) se termina Calculate_Total llamando a Terminate y por lo tanto Terminated = True, entonces se me para también Calculate_Total del Arr_List[1] ya que tengo claro que tienen el mismo nombre.

Cómo diferencia cada instancia de Calculate_Total que se crean en cada instancia propia de List_General ? Supongo que ahí está el problema.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #5  
Antiguo 08-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.440
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Yo creo que te estás liando.
Si cada formulario crea su propio thread (objeto) y lo lanza, no tiene porqué haber problemas con los nombres, y cada thread debería ser independiente.
Puedes lanzar 20 threads de la misma clase y eso no tiene porqué afectar al funcionamiento de cada uno de ellos.

En el código que has puesto, cada form (TList_General) tiene su variable del tipoTCalculate_Total; Si los lanzas adecuadamente no tiene porqué haber problemas con eso.

¿Cómo los lanzas?
¿Cómo sincronizas?
¿Qué haces al terminar los threads?

Como bien dices [s]no puedes utilizar Self[/s] en los threads, pero sí puedes acceder al form (si lo pasas como parámetro); Para acceder al formulario desde el thread (si es que te hiciera falta) puedes (y debes) utilizar el método Synchronize. Y no deberías tener ningun problema.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #6  
Antiguo 08-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.440
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Si miras este ejemplo (es muy tonto) veras que a los threads, se les pasa como parámetro un componente de tipo (TProgressbar) y aunque todos los threads son de la misma clase, cada uno modifica su componente; Tu caso es similar, aunque pasándo un TForm; Cada frmulario puede modificar "su form" sin afectar a los demás.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #7  
Antiguo 08-02-2011
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 22
gluglu Va por buen camino
En el proceso de cálculo de cada instancia de TList_General, cuando ya termino de mostrar los datos en un DBGrid, entonces creo y lanzo el Thread :

Código Delphi [-]
procedure TList_General.Initialize;
begin
 
  ....
  LabelTime.Caption := 'Consultada generada a las ' + FormatDateTime('hh:nn:ss', Time);

  Calculate_Total := TCalculate_Total.Create(True);
  Calculate_Total.FreeOnTerminate := True;
  ... paso unas variables a Calculate_Total ...
  Calculate_Total.Resume;
 
end;

En sí mismo Calculate_Total se ejecuta :

Código Delphi [-]
procedure TCalculate_Total.Execute;
begin
 
  // Realizo operaciones con la BBDD y Tablas, por lo que genero un 
  // acceso totalmente independiente en el propio Thread
 
  CTDatabase := TIBDatabase.Create(nil);
  CTDataBase.DatabaseName := DM0.IBDatabase1.DatabaseName;
  CTDataBase.LoginPrompt  := DM0.IBDatabase1.LoginPrompt;
  CTDataBase.Params       := DM0.IBDatabase1.Params;
  CTDataBase.SQLDialect   := 3;
  CTDataBase.Connected    := True;
 
  CTTransaction := TIBTransaction.Create(nil);
  CTTransaction.DefaultDataBase := CTDatabase;
  CTTransaction.StartTransaction;
 
  CTDataSet1 := TIBDataSet.Create(nil);
  CTDataSet1.Transaction := CTTransaction;
 
  ....
 
  // Realizo varios Cálculos y sincronizo de esta forma
 
  Update_Var := 1;
  Synchronize(UpdateMainForm);
 
  CTDataSet4.First;
  while not CTDataSet4.Eof do begin
 
    if Terminated then Break;
 
    with CTDataSet2 do begin
      SelectSQL.Clear;
      ....
      Prepare;
      Open;
    end;
 
    ....
 
    if Terminated then Break;
 
    Update_Var := 2;
    Synchronize(UpdateMainForm);
 
    CTTransaction.CommitRetaining;
    CTDataSet4.Next;
 
  end;
 
  if not Terminated then begin
    Update_Var := 3;
    Synchronize(UpdateMainForm);
  end;
 
  CTTransaction.Active := False;
  CTDataBase.Close;
  CTDataBase.Free;
  CTTransaction.Free;
  CTDataSet1.Free;
 
end;

procedure TCalculate_Total.UpdateMainForm;
begin
  MainForm.Arr_List[Pos_Array].UpdateForm(Update_Var);
end;

procedure TList_General.UpdateForm(Update_Var: Integer);
begin
 
  if Update_Var = 1 then begin
    ...
  end;
 
  if Update_Var = 2 then begin
    ...
  end;
 
  if Update_Var = 3 then begin
    ...
  end;
 
  Application.ProcessMessages;
 
end;

Si cierro anticipadamente (antes de que termine el Thread de realizar sus cálculos) el Form List_General correspondiente :

Código Delphi [-]
procedure TList_General.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 
  if PanelTimer.Visible then begin
    while not Calculate_Total.Terminated do begin
      Calculate_Total.Terminate;
    end;
    PanelTimer.Visible := False;
    Application.ProcessMessages;
  end;
 
  ...
 
  Action := caFree;
  MainForm.Arr_List[Pos_Array] := nil;
 
end;

No Termino el Thread Calculate_Total en ningún otro sitio de la aplicación.

Programando otros asuntos me dí cuenta de una cosa que me puse a pensar, y ello me llevó a comprobar esta parte del código correspondiente a mi formulario de listados. Ahí pude comprobar lo que indicaba anteriormente, si creo dos instancias de List_General, diferenciadas por su posición en MainForm.Arr_List[i], entonces al terminar el primero, también se para el segundo.

Según lo que indicas, Neftalí, entiendo como tu que no debería ser así.

A ver si el problema podría ser otro : En el Thread a su vez llamo a otro procedimiento que tienen que pasar un valor a una variable declarada como pública del Thread :

Código Delphi [-]
  TCalculate_Total =  class(TThread)
    procedure UpdateMainForm;
  private
    ....
  public
    Aux_Random      : Int64;
  protected
    procedure Execute; override;
  end;

Es el único problema que me puedo imaginar, si acaso. En el otro procedimiento al que se llama desde cada uno de los Threads que puedan estar activos concurrentemente, lo que hago es

Código Delphi [-]
Calculate_Total.Aux_Random := Aux_R1;

y ahí si me encontraría con el problema de no saber a qué instancia de Calculate_Total estaría pasnado el valor correspondiente.

Cómo se solucinaría esto ? Cómo haría referencia a la instancia del Thread Calculate_Total de un Form List_General en concreto cuya posición es una determinada en el Arr_List del MainForm ?

Se podría hacer esto ?
Código Delphi [-]
MainForm.Arr_List[i].Calculate_Total.Aux_Random := Aux_R1;

La verdad es que no lo he probado.

Pues lo dicho, es la única ocasión en la cual se podrían 'liar' las instancias concurrentes de Calculate_Total. De ningun otra forma.

Es por eso que pueda ser que al terminar una instancia termine también la otra ? De hecho es lo que ocurre.

Gracias de nuevo por vuestra ayuda.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #8  
Antiguo 09-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.440
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por gluglu Ver Mensaje
Es el único problema que me puedo imaginar, si acaso. En el otro procedimiento al que se llama desde cada uno de los Threads que puedan estar activos concurrentemente, lo que hago es

Código Delphi [-]
Calculate_Total.Aux_Random := Aux_R1;
No me ha quedado claro dónde está colocada esta asignación.
¿Dónde se encuentra esta línea?
¿Dentro del thread?

AÑADO:
(1) No acabo de ver de dónde sale o dónde está definida la variable Pos_Array que utilizas para acceder al array.
(2) Sigo pensando que en lugar de llegar al formulario que está asociado al thread utilizando el array, sería más sencillo que pasaras el propio formulario como parámetro al thread.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.

Última edición por Neftali [Germán.Estévez] fecha: 09-02-2011 a las 10:19:15.
Responder Con Cita
  #9  
Antiguo 08-02-2011
Avatar de yapt
yapt yapt is offline
Miembro
 
Registrado: sep 2006
Ubicación: España
Posts: 258
Poder: 19
yapt Va por buen camino
Cita:
Empezado por gluglu Ver Mensaje
Código Delphi [-]
 
unit ListGeneral;

...
 
type
  TList_General = class(TForm)
....
 
  TCalculate_Total =  class(TThread)
    procedure UpdateMainForm;
  private
    ....
  public
    ....
  protected
    procedure Execute; override;
  end;
 
var
  List_General: TList_General;
  Calculate_Total: TCalculate_Total;
 
....
implementation
....
Hola, no quisiera estorbar. Y seguro que no es de mucha ayuda, pero precisamente esto que dice Neftalí:

Cita:
En el código que has puesto, cada form (TList_General) tiene su variable del tipoTCalculate_Total; Si los lanzas adecuadamente no tiene porqué haber problemas con eso.
Es precisamente lo que yo no veo.

Código Delphi [-]
 
Calculate_Total: TCalculate_Total;
No tendría que estar definido como variable privada para cada instancia del formulario ?

Bueno, espero no añadir ruido en la conversación. Si es así, lo siento.

Saludos.
Responder Con Cita
  #10  
Antiguo 09-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.440
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por yapt Ver Mensaje
Calculate_Total: TCalculate_Total;

No tendría que estar definido como variable privada para cada instancia del formulario ?
Bueno, aunque no aparece asumo que es así; Cada formulario debe tener definida su propia variable para "su" thread. Y debe ser privada, como tú dices.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
Respuesta



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

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Firebird AND Threads Abel Garcia Firebird e Interbase 21 19-03-2008 05:07:21
uso de threads JULIPO API de Windows 2 25-07-2007 16:09:06
Threads in DLL's Gianni Varios 0 20-07-2007 22:18:23
Threads zombies Archer Varios 1 25-09-2006 19:19:38
problemas con threads dentro de un componente elcigarra OOP 26 26-05-2005 04:29:35


La franja horaria es GMT +2. Ahora son las 16:51:28.


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