In my form, when the Ontimer event occurs, a new thread is created that checks if internet connection is active. This is my code:
type
TMain = class(TForm)
...
...
TThread_Check = class(TThread)
private
TCPClient : TIdTCPClient;
procedure InternetCheck;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
var Main: TMain;
Internet, THRD_RUNNING: Boolean;
OGGI: TDate;
...
...
constructor TThread_Check.Create;
begin
inherited Create(True);
TCPClient := TIdTCPClient.Create (NIL);
try
try
TCPClient.ReadTimeout := 2000;
TCPClient.ConnectTimeout := 2000;
TCPClient.Port := 80;
TCPClient.Host := 'google.com';
TCPClient.Connect;
TCPClient.Disconnect;
INTERNET:= true;
except
INTERNET:= False;
end;
finally
TCPClient.Free;
end;
end;
procedure TThread_Check.Execute;
begin
Synchronize(InternetCheck);
end;
destructor TThread_Check.Destroy;
begin
THRD_RUNNING:=false;
end;
procedure TThread_Check.InternetCheck;
begin
if INTERNET then
begin
main.idt.Active:=true;
OGGI:=main.idt.DateTime; // Pick internet Date ad assign to OGGI
main.idt.Active:=false;
end;
end;
procedure TMain.OnTimerEvent(Sender: TObject);
Var THD : TThread_Check;
begin
if (THRD_RUNNING = False) then
begin
THRD_RUNNING := True;
thd := TThread_Check.Create;
thd.FreeOnTerminate := true;
thd.Priority := tpNormal;
Thd.Resume;
end;
end;
procedure TMain.OnCreate(Sender: TObject);
begin
THRD_RUNNING:=false;
end;
Initially it seems to work; my application starts and if internet go down, it notices (in the main form, if INTERNET=false something happens...).
The problem is that after some time the application is active, it freezes and in Windows Task Manager, the Analyze Wait Chain shows me another Thread pending, and this time if internet go down my application does not react!
What's the problem?? Please, help me! Thanks! Emanuele
The TThread
constructor runs in the thread that calls it, which in your case is the main UI thread. The only thing you are running in your worker thread is Synchronize()
, which runs its code in the main UI thread, defeating the purpose of using a worker thread at all.
You need to move your TCP connect/disconnect logic from the constructor into Execute
instead. Use Synchronize()
only to update the UI. In which case, you could just use the OnTerminate
event instead, which is already synchronized for you.
For example:
type
TMain = class(TForm)
...
end;
TThread_Check = class(TThread)
private
TCPClient : TIdTCPClient;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
var
Main: TMain;
Internet, THRD_RUNNING: Boolean;
OGGI: TDate;
...
constructor TThread_Check.Create;
begin
inherited Create(True);
TCPClient := TIdTCPClient.Create (NIL);
TCPClient.ReadTimeout := 2000;
TCPClient.ConnectTimeout := 2000;
TCPClient.Port := 80;
TCPClient.Host := 'google.com';
end;
procedure TThread_Check.Execute;
begin
try
TCPClient.Connect;
TCPClient.Disconnect;
INTERNET := True;
except
INTERNET := False;
end;
end;
destructor TThread_Check.Destroy;
begin
TCPClient.Free;
inherited;
end;
procedure TMain.OnInternetCheckDone(Sender: TObject);
begin
THRD_RUNNING := False;
if INTERNET then
begin
Main.idt.Active := true;
OGGI := Main.idt.DateTime;
Main.idt.Active := false;
end;
end;
procedure TMain.OnTimerEvent(Sender: TObject);
var
THD : TThread_Check;
begin
if (not THRD_RUNNING) then
begin
thd := TThread_Check.Create;
thd.FreeOnTerminate := True;
thd.OnTerminate := OnInternetCheckDone;
Thd.Resume;
THRD_RUNNING := True;
end;
end;
procedure TMain.OnCreate(Sender: TObject);
begin
THRD_RUNNING := False;
end;