ErikT 1 Posted January 25 I am trying to make a thread, and thought that I had understood how to pass initial values to that thread while creating it. I have used examples from Embarcadero, combined with examples from threads in this forum. However, I get an access violation at the first line of code in the constructor. Type definition of thread and form: type TPingThread = class(TThread) private LocOwnIP : in_addr; LocFromIP : Byte; LocToIP : Byte; Progress : Byte; LastByte : Byte; AddressList : TStringList; LocOwner : TComponent; Ping1 : TPing; protected procedure Execute; override; public constructor Create(AOwner : TComponent; OwnIP : in_addr; FromIP : Byte; ToIP : Byte); reintroduce; destructor Destroy; function GetProgress : Byte; function GetLastByte : Byte; end; type TForm1 = class(TForm) ListBox1: TListBox; Label1: TLabel; Label2: TLabel; Button1: TButton; Label9: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } PingThread1 : TPingThread; end; var Form1: TForm1; Quote Definition of constructor, destructor and Execute procedure: constructor TPingThread.Create(AOwner : TComponent; OwnIP : in_addr; FromIP : Byte; ToIP : Byte); begin inherited Create(false); // <-- Access violation happens here LocOwnIP := OwnIP; LocFromIP := FromIP; LocToIP := ToIP; LocOwner := AOwner; end; destructor TPingThread.Destroy; begin AddressList.Free; inherited Destroy; end; procedure TPingThread.Execute; var IPAddressRec : in_addr; i : Byte; TempInt : Integer; PingResult : Integer; begin AddressList := TStringList.Create; AddressList.Clear; Ping1 := TPing.Create(LocOwner); for i := LocFromIP to LocToIP do begin IPAddressRec.S_un_b.s_b4 := i; if (IPAddressRec.S_addr <> LocOwnIP.S_addr) then begin LastByte := i; if (LocFromIP < LocToIP) then Progress := ((i - LocFromIP) * 100) DIV (LocToIP - LocFromIP); Ping1.Address := inet_ntoa(IPAddressRec); PingResult := Ping1.Ping; if (PingResult <> 0) then AddressList.Add(Ping1.Address); end; end; end; The thread is created in a button click event: procedure TForm1.Button1Click(Sender: TObject); var DelayVal : TDateTime; Handle1 : THandle; OwnIP : in_addr; TempStr : string; begin // blah-blah... PingThread1.Create(Form1, OwnIP, 1, 31); Handle1 := PingThread1.Handle; while ((PingThread1 <> nil) and (WaitForSingleObject(Handle1, 0) <> WAIT_OBJECT_0)) do // blah-blah PingThread1.Destroy; end; As soon as TPingThread hits its first line of code, I get an access violation. It doesn't matter if it is the "inherited Create" line that comes first, or if I rearrange it like this: constructor TPingThread.Create(AOwner : TComponent; OwnIP : in_addr; FromIP : Byte; ToIP : Byte); begin LocOwnIP := OwnIP; // <-- Access violation happens here LocFromIP := FromIP; LocToIP := ToIP; LocOwner := AOwner; inherited Create(false); end; In the first example, I get the access violation on the "Inherited Create" line. In the second example, I get it on the LocOwnIP := OwnIP line. I don't understand why. I thought that the variables defined in the thread's private section was accessible to all parts of the thread. Also, I think that it looks very much like the examples I've used. Am I missing something here? Share this post Link to post
Christophe E. 12 Posted January 25 PingThread1 := TPingThread.Create(Form1, OwnIP,1,31); you also have a leak because you don't release Ping1. And I also think you're blocking the main thread, so you might as well not use a thread. Share this post Link to post
ErikT 1 Posted January 25 3 minutes ago, Christophe E. said: PingThread1 := TPingThread.Create(Form1, OwnIP,1,31); you also have a leak because you don't release Ping1. And I also think you're blocking the main thread, so you might as well not use a thread. Oh, crap. This is so obvious. I've stared myselft blind at that. Thanks! True. I need to destroy Ping1 when done. Well spotted. About blocking: This is an example, just to get the thread to work. In the final version, there is supposed to be a number of threads, and the main thread will not be blocked. Share this post Link to post
ErikT 1 Posted January 25 @Christophe E. After some further error-fixing, it now seems to work. Thank you very much! Best regards, Erik Share this post Link to post
Tommi Prami 130 Posted January 26 20 hours ago, ErikT said: type TPingThread = class(TThread) private ... public constructor Create(AOwner : TComponent; OwnIP : in_addr; FromIP : Byte; ToIP : Byte); reintroduce; destructor Destroy; override; // <---- Add override to the destructor Share this post Link to post
Remy Lebeau 1392 Posted January 26 On a side note, you should not be passing an Owner to your thread. You are creating the TPing object inside your worker thread, so don't assign a component from the main thread as its Owner. Set the Owner to nil instead, and then Free() the object when you are done using it. 2 Share this post Link to post