根据我对此主题的有限知识,以下代码应该有效。但我没有预期的结果:
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和“”(空)
拜托,我缺少什么?
谢谢!
答案 0 :(得分:6)
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
默认值为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.