Hola estoy desarrollando una aplicacion de control de acceso y asistencia con lectoras biometricas de zksoftware, estoy utilizando delphi xe4 la base de datos es mysql y para poder conectarnos via TCP/IP con las lectoras utilizamos un SDK Zkemkeeper que entrega el fabricante de las lectoras.
el problema que tenemos es el siguiente el proceso de conexion a las lectoras no es rapido si trabajamos con pocas lectoras pues los tiempos de conexion son aceptables pero si trabajamos con mas de 4 lectoras ya se hace muy lento el proceso y la informacion en las lectoras 4,5,6..n pueden demorarse hasta 3 o 4 minutos, probamos entonces con la creacion de hilos de ejecucion la idea es que se cree un hilo con cada lectora de manera que si hay problemas con la conexion de alguna de las lectoras las otras puedan recibir la informacion de manera rapida.
vamos a ver el ejemplo
Código Delphi
[-]
tprueba = class(Tthread)
lectora1:tczkem;
var
ejecutando,conectado:boolean;
error,error1,puerto1,nolectora1,ttf,version1,I:integer;
dirip1,valor1,valor2:string;
version:widestring;
descripcionordenes:Ansistring;
protected
procedure actualiza;
procedure actualiza1;
constructor create(dirip:string;nolectora,puerto:integer); overload;
public
procedure Execute; override;
procedure conectada(sender:Tobject);
procedure desconexiondelec(sender:tobject);
procedure alarma(sender: tobject; tipoalarma, nousuario,
verificada: integer);
procedure estadodoor(sender: tobject; tipoevento: integer);
procedure grabacionhuellas(sender: tobject;
EnrollNumber, FingerIndex, ActionResult, TemplateLength: integer);
procedure huellapasa(sender:Tobject);
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);
procedure tiempo1(sender: tobject);
procedure tiempo2(novalor,limite:integer);
Function descError:integer;
Procedure validaruser(lectora,nousuario:integer;validar1:boolean);
Procedure Borrarusuario(NoLectora3,Nousuario1:integer);
Procedure BorrarHuella(NoLectora2,Nousuario2,Nohuella2:integer);
Procedure GrabarHuella(nolectora4,nousuario4,nohuella4:integer;strhuella:widestring);
Procedure Actualizatiempo(nolectora4:integer);
Procedure Establececom;
Procedure escribeordenes;
Procedure conectarlectora;
end;
desde el programa principal hacemos lo siguiente creamos un arreglo dinamico dependiendo de de la cantidad de lectoras que esten registradas en la base de datos
y creamos un thread para cada uno de los items del arreglo.
Código Delphi
[-]
Var
iniciolec:array of tprueba;
Begin
procedure TForm1.FormCreate(Sender: TObject);
begin
try
datamod.SQLConnection1.Connected:=true;
except
showmessage('error de conexion a la base de datos revise parametros y ejecute nuevamente');
application.Terminate;
end;
if not datamod.Lectoras.Active then
datamod.Lectoras.Active:=True;
if datamod.Clectoras.Active then
datamod.Clectoras.Close
else
begin
datamod.Clectoras.Filter:='conexion=''TCP'' and marca=''ZKSOFT''';
datamod.Clectoras.Filtered:=True;
datamod.Clectoras.Active:=True;
end;
if not datamod.Lectoras1.Active then
datamod.Lectoras1.Active:=True;
if datamod.Clectoras1.Active then
datamod.Clectoras1.Close;
if not datamod.Usuarios.Active then
datamod.Usuarios.Active:=True;
if not datamod.Huellas.Active then
datamod.Huellas.Active:=True;
if not datamod.Actualiza.Active then
datamod.Actualiza.Active:=True;
if not datamod.ordenes.Active then
datamod.ordenes.Active:=True;
if not datamod.eventos.Active then
datamod.eventos.Active:=True;
if not datamod.ceventos.Active then
datamod.ceventos.Active:=True;
if not datamod.eventoslec.Active then
datamod.eventoslec.Active:=True;
contlec:=datamod.Clectoras.RecordCount;
SetLength(iniciolec,datamod.Clectoras.RecordCount);
SetLength(estlec,datamod.Clectoras.RecordCount);
SetLength(vallec,datamod.Clectoras.RecordCount);
datamod.Clectoras.First;
while not datamod.Clectoras.Eof do
begin datamod.Clectoras.Edit;
datamod.Clectoras.FieldByName('statuscon').AsInteger:=0;
datamod.Clectoras.FieldByName('lostcon').AsInteger:=0;
datamod.Clectoras.Post;
datamod.Clectoras.Next;
end;
varlec:=0;
datamod.Clectoras.First;
while not datamod.Clectoras.Eof do
begin
vallec[varlec]:=datamod.Clectoras.FieldByName('nolectora').AsInteger;
iniciolec[varlec]:=tprueba.create(datamod.Clectoras.FieldByName('direccionip').AsAnsiString,vallec[varlec],4370);
iniciolec[varlec].Priority:=tplower;
varlec:=varlec+1;
datamod.Clectoras.Next;
end;
timer1.Interval:=1000;
timer1.Enabled:=True;
timer2.Interval:=1000;
timer2.Enabled:=True;
actualizahoralec.Enabled:=True;
end;
constructor tprueba.create(dirip:string;nolectora,puerto:integer);
begin
inherited create(True);
dirip1:=dirip;
nolectora1:=nolectora;
puerto1:=puerto;
lectora1:=tczkem.Create(nil);
lectora1.Name := 'lectora' + Inttostr(nolectora);
lectora1.Tag := nolectora;
lectora1.OnDisConnected := Desconexiondelec;
lectora1.OnConnected:= conectada;
lectora1.OnAlarm := alarma;
lectora1.OnDoor := estadodoor;
lectora1.OnEnrollFinger := grabacionhuellas;
lectora1.OnAttTransaction := recepciondatos;
timer1:=Ttimer.Create(nil);
timer1.Enabled:=false;
timer1.Interval:=1000;
timer1.Tag:=1;
timer1.OnTimer:=tiempo1;
end;
procedure tprueba.Execute;
begin
ejecutando:=true;
lectora1.Connect_Net(dirip1, puerto1);
if conectado then
begin
lectora1.RegEvent(nolectora1, 65535); lectora1.RefreshData(nolectora1);
if lectora1.IsTFTMachine(nolectora1) then
ttf := 1
else
ttf := 0;
lectora1.GetSysOption(nolectora1, '~ZKFPVersion', version);
if version = '10' then
version1 := 10
else
version1 := 9;
end;
ejecutando:=FalsE;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
timer1.Enabled:=False;
timer1.Interval:=30000;
varlec:=0;
while varlec''<''contlec do
begin
if iniciolec[varlec].Suspended then
iniciolec[varlec].Resume
else
begin
if not iniciolec[varlec].conectado then
begin
if not iniciolec[varlec].ejecutando then
begin
if not iniciolec[varlec].Timer1.Enabled then
begin
iniciolec[varlec].Timer1.Enabled:=True; end;
end;
end;
end;
varlec:=varlec+1;
end;
timer1.Enabled:=True;
end;
End.
El problema es que cuando la lectora esta en linea el software funciona muy bien, pero si hay una lectora desconectada todo el programa incluyendo el principal se queda colgado esperando el status de la conexion de esa lectora y no se si estoy en un error pero la idea de los thread es que cada uno se comporte de manera independiente.
cual sera el problema