[英]Threadlist of TObject with Delphi - How to populate?
據我對此主題的有限了解,以下代碼應該可以工作。 但是我沒有預期的結果:
type
TClient = class(TObject)
Host: String;
end;
var
Clients: TThreadList;
const
Hosts: Array[0..5] of String = ('HOST1', 'HOST2', 'HOST3', 'HOST4', 'HOST5', 'HOST6');
var
I: Integer;
List: TList;
Client: TClient;
begin
try
for I := Low(Hosts) to High(Hosts) do
begin
Client := TClient.Create;
with Client Do
try
Host := Hosts[I];
List := Clients.LockList;
try
Clients.Add(Client);
finally
Clients.UnlockList;
end;
finally
Client.Free;
end;
end;
except
on E:Exception Do ShowMessage(E.Message);
end;
// RESULT TEST
List := Clients.LockList;
try
I := List.Count;
S := TClient(List.Items[0]).Host;
finally
Clients.UnlockList;
end;
ShowMessage(IntToStr(I));
ShowMessage(S);
我的預期結果是6和HOST1,但我得到1和“”(空)
拜托,我想念的是什么?
謝謝!
List := Clients.LockList;
try
Clients.Add(Client); // <--- mistake here
finally
Clients.UnlockList;
end;
習慣用法是通過調用LockList
鎖定列表,並返回可變列表。 因此,您需要調用Add
on List
。
List := Clients.LockList;
try
List.Add(Client);
finally
Clients.UnlockList;
end;
也就是說, TThreadList
確實提供了一個內部使用LockList
的Add
方法。 調用該Add
失敗的原因是您使用了Duplicates
的默認值dupIgnore
。 並且您每次都傳遞相同的內存地址。
為什么每次的內存地址都相同? 好吧,您犯的另一個錯誤是銷毀TClient
對象並在以后引用它們。 我猜內存管理器正在重新使用剛釋放的內存。
您可能需要將Duplicates
設置為dupAccept
。 至少您需要意識到它有潛在的影響。
該程序產生您想要的輸出:
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
TClient = class(TObject)
Host: String;
end;
const
Hosts: Array[0..5] of String = ('HOST1', 'HOST2', 'HOST3', 'HOST4',
'HOST5', 'HOST6');
var
I: Integer;
List: TList;
Client: TClient;
Clients: TThreadList;
begin
Clients := TThreadList.Create;
Clients.Duplicates := dupAccept;
for I := Low(Hosts) to High(Hosts) do
begin
Client := TClient.Create;
Client.Host := Hosts[I];
List := Clients.LockList;
try
List.Add(Client);
finally
Clients.UnlockList;
end;
end;
List := Clients.LockList;
try
Writeln(List.Count);
Writeln(TClient(List.Items[0]).Host);
finally
Clients.UnlockList;
end;
end.
或者可以進一步簡化循環:
for I := Low(Hosts) to High(Hosts) do
begin
Client := TClient.Create;
Client.Host := Hosts[I];
Clients.Add(Client);
end;
為了簡單起見,我忽略了執行任何釋放操作。 顯然,在真實代碼中,您不會泄漏這種代碼的方式。
我個人不喜歡這門課。 不在這個泛型時代。 您確實應該查看TThreadList<T>
。
{$APPTYPE CONSOLE}
uses
SysUtils, Classes, Generics.Collections;
type
TClient = class
Host: string;
constructor Create(AHost: string);
end;
constructor TClient.Create(AHost: string);
begin
inherited Create;
Host := AHost;
end;
const
Hosts: array[0..5] of string = ('HOST1', 'HOST2', 'HOST3', 'HOST4',
'HOST5', 'HOST6');
var
Host: string;
List: TList<TClient>;
Clients: TThreadList<TClient>;
begin
Clients := TThreadList<TClient>.Create;
Clients.Duplicates := dupAccept;
for Host in Hosts do
Clients.Add(TClient.Create(Host));
List := Clients.LockList;
try
Writeln(List.Count);
Writeln(List.First.Host);
finally
Clients.UnlockList;
end;
end.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.