I have a problem with Delphi 6 and Indy's TIdIcmpClient component.
I get this message when compiling the following code, in the marked line (51):
FPing.OnReply := OnPingReply;
[Error] fire.pas(51): Incompatible types: 'TComponent' and 'TIdIcmpClient'
How should I fix it?
unit fire;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
IdIcmpClient;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TMyThread = class(TThread)
private
FIndex: Integer;
FPing: TIdIcmpClient;
FIP: string;
protected
procedure Execute; override;
procedure OnPingReply(ASender: TIdIcmpClient; AReplyStatus: TReplyStatus);
public
constructor Create(AIndex: Integer);
destructor Destroy; override;
end;
constructor TMyThread.Create(AIndex: Integer);
begin
inherited Create(False);
FIndex := AIndex;
FIP := '192.168.1.' + IntToStr(FIndex + 1);
FPing := TIdIcmpClient.Create(nil);
FPing.Host:=FIP;
FPing.ReceiveTimeout:=1500;
FPing.OnReply := OnPingReply;
end;
destructor TMyThread.Destroy;
begin
FPing.Free;
inherited;
end;
//var// icmp:array[0..10] of TIdIcmpClient;
// ip:string;
procedure TMyThread.Execute; // aici e ce face thread-ul
var
i: Integer;
begin
FPing.Ping;
// ICMP.Ping('a',1000);
// Sleep(1300);
// form1.memo1.lines.add(IntToStr(findex)+' '+ICMP.ReplyStatus.fromipaddress);
for i := 1 to 1 do
begin
// 'findex' este indexul thread-ului din matrice
form1.memo1.lines.add(inttostr(findex)+' Thread running...');
application.ProcessMessages;
Sleep(1000);
end;
end;
procedure TMyThread.OnPingReply(ASender: TIdIcmpClient; AReplyStatus: TReplyStatus);
begin
if AReplyStatus.BytesReceived > 0 then
form1.memo1.Lines.add(FIP+ ' is reachable')
else
form1.memo1.Lines.add(FIP+ ' is not reachable: ');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyThreads: array[0..10] of TMyThread;
// icmp:array[0..10] of TIdIcmpClient;
i: Integer;
begin
{ for i := 0 to 10 do //10 fire
begin
icmp[i]:=tidicmpclient.create(nil);
icmp[i].ReceiveTimeout:=1200;
ip:=Format('%s.%d', ['192.168.1', i]);
ICMP[i].Host :=ip;
end; }
for i := 0 to 10 do //10 fire
begin
MyThreads[i] := TMyThread.Create(i);
MyThreads[i].Resume;
application.ProcessMessages;
end;
// Readln;
for i := 0 to 10 do
begin
MyThreads[i].Free;
// icmp[i].Free;
end;
end;
end.
I expected it to be compilable, but I don't see the reason why it is not.
Your event handler is declared wrong. The
ASenderparameter needs to beTComponentrather thanTIdIcmpClient, and theAReplyStatusparameter needs to beconst:That being said, you don't need to use the
OnReplyevent at all in this situation.TIdIcmpClientoperates synchronously, so you can simply use theTIdIcmpClient.ReplyStatusproperty after theTIdIcmpClient.Ping()method exits:Also, you must synchronize with the main UI thread when accessing UI controls in a worker thread. You can use
TThread.Synchronize()method for that.And, you do not need to call
Application.ProcessMessages()in a worker thread. Doing so will have no effect on the main UI thread.With all of that said, try something more like this: