TObject与Delphi的线程列表-如何填充? [英] Threadlist of TObject with Delphi - How to populate?
问题描述
据我对这一主题的有限了解,以下代码应该可以工作.但是我没有预期的结果:
From my limited knowledge about this subject, the following code should work. But I have not the expected result:
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和"(空)
My expected result would be 6 and HOST1, but I got 1 and "" (empty)
拜托,我想念的是什么?
Please, what I am missing?
谢谢!
推荐答案
List := Clients.LockList;
try
Clients.Add(Client); // <--- mistake here
finally
Clients.UnlockList;
end;
习惯用法是通过调用LockList
锁定列表,并返回可变列表.因此,您需要在List
上调用Add
.
The idiom is that you lock the list with a call to LockList
and that returns a mutable list. So you need to call Add
on List
.
List := Clients.LockList;
try
List.Add(Client);
finally
Clients.UnlockList;
end;
也就是说,TThreadList
确实提供了一种内部使用LockList
的Add
方法.您对Add
的调用失败的原因是您使用了Duplicates
的默认值dupIgnore
.并且您每次都传递相同的内存地址.
That said, TThreadList
does offer an Add
method that internally uses LockList
. The reason that your call to that Add
was failing is that you have used the default value of Duplicates
which is dupIgnore
. And you were passing the same memory address each time.
为什么每次的内存地址都相同?好吧,您犯的另一个错误是销毁TClient
对象并在以后引用它们.我猜内存管理器正在重新使用刚刚释放的内存.
Why was the memory address the same each time? Well, the other mistake you made was to destroy your TClient
objects and refer to them later. I guess the memory manager was re-using the memory that you just deallocated.
您可能希望将Duplicates
设置为dupAccept
.至少您需要意识到它具有潜在的影响.
You might want to set Duplicates
to dupAccept
. At the very least you need to be aware that it has a potential impact.
该程序会产生所需的输出:
This program produces your desired output:
{$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.
或者可以进一步简化循环:
Or the loop could be simplified even further:
for I := Low(Hosts) to High(Hosts) do
begin
Client := TClient.Create;
Client.Host := Hosts[I];
Clients.Add(Client);
end;
为了简单起见,我忽略了执行任何重新分配.显然,在真实代码中,您不会泄漏这种代码的方式.
I neglected to perform any deallocations for the sake of a simpler exposition. Obviously in real code you wouldn't leak the way this code does.
我个人不喜欢此类.不在这个泛型时代.您确实应该查看TThreadList<T>
.
Personally I'm not a fan of this class. Not in this age of generics. You really should be looking at 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.
这篇关于TObject与Delphi的线程列表-如何填充?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!