praba
praba

Reputation: 1084

Timer process affect the user interface in delphi

i have developed application for read information from card reader. Here i have used timer for get the information each five second, so every five second the user interface getting slow because it's get the information from reader. how to run the timer in background with out affecting user interface

unit frmVistorreg;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;

type
 thread1=class(TThread)
 private
 FEvent: THandle;
 protected
 procedure Execute; override;
 public
 procedure MyTerminate;
end;


TForm3 = class(TForm)     
txt_name: TEdit;   
txt_cardno.Text  TEdit;        

private

public

end;

var
Form3: TForm3;

implementation

{$R *.dfm}


procedure thread1.Execute;
var
idcard_info :array[0..1024*5] of byte;
flag :Integer;
portflag :Integer;
st :TStrings;
str :string;  
begin

FEvent:= CreateEvent(nil, False, false, nil);
try
while not Terminated do begin
if  MainForm.PortFlag=0 then
begin

 Form3.Label11.Caption:='port has been successfully opened';
 Form3.Label11.Font.Color :=32768;
 flag := GetIdCardInfo(@idcard_info[0],1024*5,5);
 str := byteArray2Str(@idcard_info[0],1024*5);

        if(flag=0) then
        begin
           st := TStringList.Create;
           try
              SplitStr('^_^',str,st);
              Form3.txt_name.Text := st.Strings[0]; 
              Form3.txt_cardno.Text := st.Strings[5]; 
          finally
        st.Free;
          end;
        end;

end
else
begin 

Form3.Label11.Caption:='Please open the port';
Form3.Label11.Font.Color:=clRed;
end;

if WaitForSingleObject(FEvent, 500) <> WAIT_TIMEOUT // 5 seconds timeout
then Terminate;
end;

finally
CloseHandle(FEvent);
end;
end;


procedure thread1.MyTerminate;
begin
 SetEvent(FEvent);
end;


procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
var
Objthread1:thread1;
begin   
Objthread1.MyTerminate;
Action := caFree;
end;


procedure TForm3.FormCreate(Sender: TObject);
var
Objthread1:thread1;
begin
Objthread1:=thread1.Create(false);  
end;

end.

when i close the form have error like

Project MDIAPP.exe raised exception class EAccessViolation with message 'Access violation at address 0051B9F1 in module 'MDIAPP.exe'. Read of address 00000198'.

how can i solve this.

Upvotes: 2

Views: 1792

Answers (1)

kludg
kludg

Reputation: 27493

You need not a timer component for that, you need a background thread. A simplest solution is to use Sleep function in the thread:

unit Unit2;

interface

uses
  Classes;

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

implementation

procedure TMyThread.Execute;
begin
  while not Terminated do begin
// do your processing here
    Sleep(5000);   // wait 5 seconds
  end;
end;

end.

A better approach is to use WaitForSingleObject and an event instead of Sleep to be able to terminate your background thread immediately without 5 seconds delay:

unit Unit2;

interface

uses
  Windows, Classes;

type
  TMyThread = class(TThread)
  private
    FEvent: THandle;
  protected
    procedure Execute; override;
  public
    procedure MyTerminate;
  end;

implementation

procedure TMyThread.Execute;
begin
  FEvent:= CreateEvent(nil, False, False, nil);
  try
    while not Terminated do begin
// do your processing here
// ..
      if WaitForSingleObject(FEvent, 5000) <> WAIT_TIMEOUT // 5 seconds timeout
        then Terminate;
    end;
  finally
    CloseHandle(FEvent);
  end;
end;

procedure TMyThread.MyTerminate;
begin
  SetEvent(FEvent);
end;

end.

To terminate TMyThread instance on closing a form call MyTerminate method from OnClose event handler of a form.

And yes, it is interesting to know what error message you receive, not just 'showing error'.

Upvotes: 10

Related Questions