TIdTelnet
- многопоточный компонент.Он имеет внутренний поток, который непрерывно читает данные из сокета, вызывая событие TIdTelnet.OnDataAvailable
всякий раз, когда доступен буфер данных.
TIdTelnet
является потомком TIdTCPClient
.Посмотрите в исходном файле IdTelnet.pas, чтобы увидеть, как это реализовано.Вы можете сделать что-то подобное в своем собственном коде, вызывая TIdIOHandler.ReadLn()
в своем собственном потоке, например:
type
TMyThread = class(TThread)
private
FConn: TIdTCPConnection;
protected
procedure Execute; override;
public
constructor Create(AConn: TIdTCPConnection); reintroduce;
end;
constructor TMyThread.Create(AConn: TIdTCPConnection);
begin
inherited Create(False);
FConn := AConn;
end;
procedure TMyThread.Execute;
var
S: String;
begin
while not Terminated do
begin
S := FConn.IOHandler.ReadLn(...);
...
end;
end;
var
Thread: TMyThread = nil;
procedure TForm1.ConnectButtonClick(Sender: TObject);
begin
IdTCPClient1.Connect;
try
Thread := TMyThread.Create(IdTCPClient1);
except
IdTCPClient1.Disconnect;
raise;
end;
end;
procedure TForm1.DisconnectButtonClick(Sender: TObject);
begin
if Assigned(Thread) then Thread.Terminate;
try
IdTCPClient1.Disconnect;
finally
if Assigned(Thread) then
begin
Thread.WaitFor;
FreeAndNil(Thread);
end;
end;
end;
Если вы не хотите использовать поток, вы можете вместо этого использовать таймер.Чтобы убедиться, что ваш поток таймера (например, основной поток) не заблокирован без необходимости, используйте метод TIdIOHandler.CheckForDataOnSource()
с небольшим таймаутом, когда TIdIOHandler.InputBuffer
пуст, перед тем как вызывать TIdIOHandler.ReadLn()
только при наличии данных, например:
procedure TForm1.ConnectButtonClick(Sender: TObject);
begin
IdTCPClient1.Connect;
ReadTimer.Enabled := True;
end;
procedure TForm1.DisconnectButtonClick(Sender: TObject);
begin
ReadTimer.Enabled := False;
IdTCPClient1.Disconnect;
end;
procedure TForm1.ReadTimerElapsed(Sender: TObject);
var
S: String;
begin
if IdTCPClient1.IOHandler.InputBufferIsEmpty then
begin
IdTCPClient1.IOHandler.CheckForDataOnSource(10);
if IdTCPClient1.IOHandler.InputBufferIsEmpty then Exit;
end;
S := IdTCPClient1.IOHandler.ReadLn(...);
...
end;