List := Clients.LockList;
try
Clients.Add(Client); // <--- mistake here
finally
Clients.UnlockList;
end;
习惯用法是您通过调用锁定列表LockList
并返回一个可变列表。所以你需要打电话Add
。List
List := Clients.LockList;
try
List.Add(Client);
finally
Clients.UnlockList;
end;
也就是说,TThreadList
确实提供了Add
一种内部使用的方法LockList
。您调用Add
失败的原因是您使用了默认值Duplicates
is 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.