Guy*_*ush 1 delphi multithreading list object tobject
根据我对此主题的有限知识,以下代码应该有效.但我没有预期的结果:
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);
Run Code Online (Sandbox Code Playgroud)
我的预期结果是6和HOST1,但我得到1和""(空)
拜托,我错过了什么?
谢谢!
List := Clients.LockList;
try
Clients.Add(Client); // <--- mistake here
finally
Clients.UnlockList;
end;
Run Code Online (Sandbox Code Playgroud)
成语是你通过调用锁定列表LockList并返回一个可变列表.所以,你需要调用Add上List.
List := Clients.LockList;
try
List.Add(Client);
finally
Clients.UnlockList;
end;
Run Code Online (Sandbox Code Playgroud)
也就是说,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.
Run Code Online (Sandbox Code Playgroud)
或者循环可以进一步简化:
for I := Low(Hosts) to High(Hosts) do
begin
Client := TClient.Create;
Client.Host := Hosts[I];
Clients.Add(Client);
end;
Run Code Online (Sandbox Code Playgroud)
为了更简单的阐述,我忽略了执行任何解除分配.显然,在实际代码中,您不会泄漏此代码的方式.
就个人而言,我不是这个班的粉丝.不是在这个泛型的时代.你真的应该看看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.
Run Code Online (Sandbox Code Playgroud)