我正在尝试将单线程应用程序转换为多线程应用程序。
基本上,我想每隔10秒同时检查50个端口,看看它们是在线还是离线。
我正在使用列表框加载所有ip和端口(127.0.0.1:50008),我解析了ip和端口号并使用此函数检查它:
uses idTCPclient;
function IsPortActive(AHost : string; APort : string): boolean;
var
IdTCPClient : TIdTCPClient;
begin
Result := False;
try
IdTCPClient := TIdTCPClient.Create(nil);
try
IdTCPClient.Host := AHost;
IdTCPClient.Port := strtoint(APort);
IdTCPClient.ConnectTimeout:=50;
IdTCPClient.Connect;
Result := True;
finally
IdTCPClient.Free;
end;
except
//Ignore exceptions
end;
end;
以下是开始检查端口并相应地发出结果信号的过程:
procedure TForm2.Button1Click(Sender: TObject);
begin
if isportactive('127.0.0.1','50008') then
listbox_online.items.add(ip+''+port)
else
listbox_offline.items.add(ip+''+port);
end;
有人可以指导我如何将其转换为可以接受IP和端口作为参数的线程吗?
答案 0 :(得分:3)
编写线程的一种方法就是这个。
我没有添加任何额外的TNotifyEvent
方法,因为您可以在线程的OnTerminate
事件中查找所需的属性。
type
THostChecker = class(TThread)
strict private
FIdTCPClient: TIdTCPClient;
FHost: string;
FPort: Integer;
FConnectTimeout: Integer;
FIsPortActive: Boolean;
protected
procedure Execute; override;
public
constructor Create(const AHost: string; APort: Integer; AConnectTimeout: Integer = 50; CreateSuspended: Boolean = False);
property IsPortActive: Boolean read FIsPortActive;
property Host: string read FHost;
property Port: Integer read FPort;
destructor Destroy; override;
end;
implementation
{ THostChecker}
constructor THostChecker.Create(const AHost: string; APort: Integer; AConnectTimeout: Integer; CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FHost := AHost;
FPort := APort;
FConnectTimeout := AConnectTimeout;
FIdTCPClient := TIdTCPClient.Create(nil);
FIsPortActive := False;
end;
destructor THostChecker.Destroy;
begin
FIdTCPClient.Free;
inherited;
end;
procedure THostChecker.Execute;
begin
inherited;
with FIdTCPClient do begin
Host := FHost;
Port := FPort;
ConnectTimeout := FConnectTimeout;
Connect;
FIsPortActive := True;
end;
end;
以下是相关部分的表格:
procedure TForm4.Button1Click(Sender: TObject);
const
hosts: array [0..6] of string = ('google.com', 'stackoverflow.com', 'youtube.com', 'foo.org', 'null.org', 'porn.com', 'microsoft.com');
var
i: Integer;
begin
for i:=Low(hosts) to High(hosts) do
with THostChecker.Create(hosts[i], 80, 50, False) do begin
OnTerminate := HostCheckerTerminate;
FreeOnTerminate := True;
end;
end;
procedure TForm4.HostCheckerTerminate(Sender: TObject);
var
hostChecker: THostChecker;
ex: Exception;
hostAndPort: string;
begin
hostChecker := THostChecker(Sender);
ex := Exception(hostChecker.FatalException);
if Assigned(ex) then
//do something useful here or don't evaluate ex at all
hostAndPort := Format('%s:%d', [hostChecker.Host, hostChecker.Port]);
if hostChecker.IsPortActive then
listbox_online.items.add(hostAndPort)
else
listbox_offline.items.add(hostAndPort);
end;
属性FreeOnTerminate
设置为True
,以避免为线程本身调用Free
。
在线程的OnTerminate
事件中执行的代码已在调用线程中同步。
线程不会在调用阶段引发异常,但您可以检查Execute
方法中是否发生了异常,评估FatalException
事件中的OnTerminate
属性。