I do write an app, that uses Indy 10 TCP/IP Client and TThread. The app connects to the server on Form.OnCreate event and disconnects from it on Form.OnClose event. Connection to the server is realized in TThread.
When I do start the app while ethernet cable is disconnected and try to close app until connection time out, then I do get these two exeptions:
- Socket.Error #10038Socket operation on non-socket.
- Thread Error: The handle is invalid(6).
If I try to close app while it is connected to client, then I get only this exeption:
- Thread Error: The handle is invalid(6).
If I close the app while thread executes sleep, then no exeptions I do get.
What am I doing wrong, or it is normal behavior?
TThread class code:
type
connThread = class (TThread)
protected
procedure Execute ; override;
private
procedure Sinchronizuot(zinute : string; spalva : TColor; tmrNormalReconn : Boolean);
end;
Form.OnCreate code:
procedure TForm1.FormCreate(Sender: TObject);
begin
fellnerConn := connThread.Create(True);
fellnerConn.FreeOnTerminate := True;
fellnerConn.Start;
end;
Form.OnClose code:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if fellnerConn <> nil then
fellnerConn.Terminate;
if idCl.Connected then
begin
try
idCl.Disconnect;
idCl.IOHandler.Free;
finally
if fellnerConn <> nil then
begin
fellnerConn.WaitFor;
fellnerConn := nil;
end;
end;
end;
end;
Thread execute code:
procedure connThread.Execute;
var
zinute : string;
spalva : TColor;
begin
inherited;
while not Form1.fellnerConn.Terminated do
begin
zinute := 'Jungiamasi prie Moxa serverio ' + Form1.idCl.Host;
spalva := clYellow;
Synchronize(procedure
begin
Sinchronizuot(zinute, spalva, False);
end
);
try
Form1.idCl.Connect;
except
on E: Exception do
begin
zinute := e.Message + ' Nepavyko prisijungti.';
spalva := clWebRed;
Synchronize(procedure
begin
Sinchronizuot(zinute, spalva, False);
end);
Sleep(1000);
end;
end;
end;
end;
The socket error is to be expected. The main thread is closing the socket while the worker thread is still using it.
But, you cannot use
TThread.WaitFor()withFreeOnTerminate=True, that is why you keep getting "the handle is invalid" errors. The thread object is being destroyed, closing its handle, whileWaitForis still using it.You should not be using
FreeOnTerminatelike this. It should only be used for start-and-forget type of threads. As soon as you need to keep a reference to a thread object, you should not use itsFreeOnTerminateproperty anymore.Either way, you should be using the thread's
OnTerminateevent so you cannilyour reference to the thread as soon as the thread has terminated.Try something more like this: