PDA

Ver la Versión Completa : Problema con multihilos y zeos


JULIPO
14-04-2011, 14:42:29
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.


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

var
Form2: TForm2;
FILAS:ARRAY OF TFILA;
lectoras:array of tlectoras;


cero un array de hilos para poder asignarle un hilo a cada lectora.

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

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

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.

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