Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Problema con multihilos y zeos (https://www.clubdelphi.com/foros/showthread.php?t=73312)

JULIPO 14-04-2011 14:42:29

Problema con multihilos y zeos
 
Estoy desarrollando un aplicativo para la conexion de unas lectoras biometricas
la idea es que cada lectora tenga su propio hilo ya que la administracion de la informacion hacia la lectora es algo demorada, en caso de no utilizar hilos el sistema requiere que cada una espere su turno hasta que la otra termine el proceso que este realizando algo que puede demorar hasta 14 segundos por lectora y si tienes 8 lectoras, la informacion en la lectora 8 se demora mas o menos 2 minutos en ser procesada.

el aplicativo lo desarrolle en delphi 2010 con componentes Zeos para la base de datos y la libreria propia de la lectora biometrica TczKem.

Código Delphi [-]
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, cyBaseButton, cyBitBtn, ZDataset, DB,
  ZAbstractRODataset, ZAbstractDataset, ZAbstractConnection, ZConnection,
  OleCtrls, zkemkeeper_TLB, ExtCtrls,hilo1;
aqui incluyo la libreria donde estan los procedimientos de los hilos que voy a crear
Código Delphi [-]
var
  Form2: TForm2;
  FILAS:ARRAY OF TFILA;
  lectoras:array of tlectoras;
cero un array de hilos para poder asignarle un hilo a cada lectora.
Código Delphi [-]
    contador:=0;
    if not zq1.IsEmpty then
     begin
      SETLENGTH(lectoras,zq1.RecordCount);
      while not zq1.Eof do
       begin
         lectoras[contador]:=tlectoras.create(Button1,listbox1,'localhost','biodynacceso','Usuario','Password',zq1.FieldByName(  'direccionip').AsString,3306,zq1.FieldByName('nolectora').AsInteger,zq1.FieldByName('puertoip').AsIn  teger);
         contador:=contador+1;
         zq1.Next;
       end;
     end;
asi creo los hilos en ejecucion

Aqui les muestro la libreria hilo1
Código Delphi [-]
 type
 tlectoras=class(Tthread)
 lectora1: TCZKEM;
 ZConnection1: TZConnection;
 ZQuery1: TZQuery;
 ZQuery2,Zquery3, Zquery4, Zquery5,zq1: TZQuery;
 labelito1:Tlistbox;
 Timer1,timer2,timer3:ttimer;
 boton1:Tbutton;
 private

 protected
   procedure Execute; override;
   procedure actualizar1;
   procedure actualizar2;
   procedure tiempo1(sender:tobject);
   procedure tiempo2(sender:tobject);
   procedure tiempo3(sender:tobject);
   procedure Desconexiondelec(sender:tobject);
   procedure grabacionhuellas(sender: TObject; EnrollNumber,
                              FingerIndex, ActionResult, TemplateLength: Integer);
   procedure grabarusuario(lectora,nousuario,administrador:integer;nick:string;validar1:boolean);
   procedure recepciondatos(sender: TObject; EnrollNumber,IsInValid, AttState,
    VerifyMethod, Year,  Month, Day, Hour,Minute,Second:integer);
 public
   host1,databasename1,user1,password1,ip1,horario:string;
   portdb1,nolectora1,portip1:integer;
   actualizatiempo,conexion,error,error1,bloqueo,validar:boolean;
   buscarconexion,actualizadatos:boolean;
   cantidad,tamano:integer;
   template1:widestring;
   mensaje,tipolectora,variable:string;
   constructor create(boton:tbutton;labellito:tlistbox;host,databasename,user,password,ip:string;portdb,nolectora,p  ortip:integer);
 end;
En el constructor la idea es que pueda pasar parametros al hilo, ademas creo los componentes de base de datos, y de lectoras biometricas que voy a utilizar aqui la idea es que cada lectora busque en la base de datos los comandos especificos para cada lectora ejemplo si el comando es para la lectora 1 solo busque los comandos para esa lectora unica (tienen una unica direccion IP y puerto)

ahora el procedimiento de creacion
Código Delphi [-]
constructor tlectoras.create(boton:tbutton;labellito:tlistbox;host: string; databasename: string; user: string; password: string; ip: string; portdb: Integer; nolectora: Integer; portip: Integer);
begin
  inherited create(false);
  Timer1:=TTimer.Create(nil);
  Timer1.Name:='Timer1'+inttostr(nolectora);
  variable:=inttostr(nolectora*100)+inttostr(1);
  timer1.Tag:=strtoint(variable);
  timer1.Enabled:=false;
  timer1.Interval:=300000;
  timer1.OnTimer:=tiempo1;
  Timer2:=TTimer.Create(nil);
  Timer2.Name:='Timer2'+inttostr(nolectora);
  variable:=inttostr(nolectora*100)+inttostr(2);
  timer2.Tag:=strtoint(variable);
  timer2.Enabled:=false;
  timer2.Interval:=30000;
  timer2.OnTimer:=tiempo2;
  Timer3:=TTimer.Create(nil);
  Timer3.Name:='Timer3'+inttostr(nolectora);
  variable:=inttostr(nolectora*100)+inttostr(3);
  timer3.Tag:=strtoint(variable);
  timer3.Enabled:=false;
  timer3.Interval:=10000;
  timer3.OnTimer:=tiempo3;
  labelito1:=labellito;
  boton1:=boton;
  host1:=host;
  databasename1:=databasename;
  user1:=user;
  password1:=password;
  ip1:=ip;
  portdb1:=portdb;
  nolectora1:=nolectora;
  portip1:=portip;
  zconnection1:=tzconnection.Create(nil);
  zconnection1.Name:='zconnection'+inttostr(nolectora);
  zconnection1.HostName:=host;
  zconnection1.Database:=databasename;
  zconnection1.User:=user;
  zconnection1.Password:=password;
  zconnection1.Protocol:='mysql-5';
  zconnection1.Port:=portdb;
  zconnection1.Connect;
  variable:=inttostr(nolectora)+inttostr(4);
  zconnection1.Tag:=strtoint(variable);
  zquery1:=tzquery.Create(nil);
  zquery1.Name:='Zquery1'+inttostr(nolectora);
  variable:=inttostr(nolectora)+inttostr(5);
  zquery1.Tag:=strtoint(variable);
  zquery1.Connection:=zconnection1;
  zquery2:=tzquery.Create(nil);
  zquery2.Name:='Zquery2'+inttostr(nolectora);
  variable:=inttostr(nolectora)+inttostr(6);
  zquery2.Tag:=strtoint(variable);
  zquery2.Connection:=zconnection1;
  zquery3:=tzquery.Create(nil);
  zquery3.Name:='Zquery3'+inttostr(nolectora);
  variable:=inttostr(nolectora)+inttostr(7);
  zquery3.Tag:=strtoint(variable);
  zquery3.Connection:=zconnection1;
  zquery4:=tzquery.Create(nil);
  zquery4.Name:='Zquery4'+inttostr(nolectora);
  variable:=inttostr(nolectora)+inttostr(8);
  zquery4.Tag:=strtoint(variable);
  zquery4.Connection:=zconnection1;
  zquery5:=tzquery.Create(nil);
  zquery5.Name:='Zquery5'+inttostr(nolectora);
  variable:=inttostr(nolectora)+inttostr(9);
  zquery5.Tag:=strtoint(variable);
  zquery5.Connection:=zconnection1;
  zq1:=tzquery.Create(nil);
  zq1.Name:='Zq1'+inttostr(nolectora);
  variable:=inttostr(nolectora*100)+inttostr(4);
  zq1.Tag:=strtoint(variable);
  zq1.Connection:=zconnection1;
  if zquery2.Active then
   zquery2.Close;
  zquery2.SQL.Clear;
  zquery2.SQL.Text:='select * from actualiza where  (lectora=:data1) and (terminado=0)';
  zquery2.ParamByName('data1').AsInteger:=nolectora1;
  zquery2.Open;
  if zquery4.Active then
   zquery4.Close;
  zquery4.SQL.Clear;
  zquery4.SQL.Text:='select * from lectoras where nolectora=:data1';
  zquery4.ParamByName('data1').AsInteger:=nolectora1;
  zquery4.Open;
  if not zquery4.IsEmpty then
   tipolectora:=zquery4.FieldByName('tipolectora').AsString;
  lectora1:=TCZKEM.Create(nil);
  lectora1.Name:='lectora'+inttostr(nolectora);
  lectora1.Tag:=nolectora1;
  lectora1.OnDisConnected:=Desconexiondelec;
  lectora1.OnEnrollFinger:=grabacionhuellas;
  LECTORA1.OnAttTransaction:=recepciondatos;
  conexion:=lectora1.Connect_Net(ip1,portip);
  if conexion then
   mensaje:='Lectora No '+ Inttostr(nolectora1)+' conectada'
  else
   mensaje:='Lectora No '+ Inttostr(nolectora1)+' Desconectada';
  Synchronize(actualizar1);
  cantidad:=0;
  timer1.Enabled:=true;
  timer2.Enabled:=true;
  Timer3.Enabled:=true;
end;
ahora cuando el hilo se ejecuta debe buscar y realizar las operaciones indicadas en la base de datos.
Código Delphi [-]
procedure tlectoras.Execute;
begin
while not terminated do
 begin
    try
     zconnection1.Ping;
    except
     zconnection1.Disconnect;
     zconnection1.Connect;
    end;

       if zquery2.Active then
        zquery2.Close;
       zquery2.SQL.Clear;
       zquery2.SQL.Text:='select * from actualiza where  (lectora=:data1) and (terminado=0)';
       zquery2.ParamByName('data1').AsInteger:=nolectora1;
       zquery2.Open;
       zquery2.First;
       if not zquery2.IsEmpty then
        begin
         while not zquery2.Eof do
          begin
          //********************************************************************
          // verirficamos si hay orden de cancelacion de operacion
          //********************************************************************
           if zquery2.FieldByName('evento').AsString='cancelalectora' then
            begin
             conexion:=LECTORA1.CancelOperation;
             LECTORA1.EnableDevice(nolectora1,true);
             conexion:=LECTORA1.StartIdentify;
             conexion:=LECTORA1.RefreshData(nolectora1);
             zquery2.Edit;
             zquery2.FieldByName('terminado').AsInteger:=1;
             zquery2.Post;
             bloqueo:=False;
            end;
end;
End;
End;
End;
Ahora el problema en la depuracion veo que se crean los hilos de manera correcta, pero cuando se esta ejecutando el hilo realiza la busqueda en la base de datos para el primer hilo de ahi en adelante me aparece que el query Zquery2 esta cerrado para los demas hilos y no se cual es mi error

Cualquier ayuda sera bienvenida

de antemano grscias


La franja horaria es GMT +2. Ahora son las 23:37:02.

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