gpt4 book ai didi

multithreading - 使用 Delphi 的 TObject 线程列表 - 如何填充?

转载 作者:行者123 更新时间:2023-12-03 19:03:00 26 4
gpt4 key购买 nike

根据我对这个主题的有限了解,以下代码应该有效。但是我没有预期的结果:

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 来锁定列表。并返回一个可变列表。所以你需要调用AddList .

List := Clients.LockList;
try
List.Add(Client);
finally
Clients.UnlockList;
end;

也就是说,TThreadList确实提供 Add内部使用 LockList 的方法.你调用那个Add的原因失败是因为您使用了默认值 Duplicates这是dupIgnore .而且你每次都传递相同的内存地址。

为什么每次内存地址都一样?嗯,你犯的另一个错误是毁掉你的 TClient对象并在以后引用它们。我猜内存管理器正在重新使用您刚刚释放的内存。

您可能想要设置 DuplicatesdupAccept .至少您需要意识到它具有潜在影响。

这个程序产生你想要的输出:

{$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;

为了更简单的说明,我忽略了执行任何重新分配。显然,在实际代码中,您不会像这段代码那样泄漏。

就我个人而言,我不是这个类(class)的粉丝。不是在这个泛型时代。你真的应该看看 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.

关于multithreading - 使用 Delphi 的 TObject 线程列表 - 如何填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27555342/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com