Threadlist of TObject with Delphi - How to populate?

╄→гoц情女王★ 提交于 2019-12-24 12:36:22

问题


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);

My expected result would be 6 and HOST1, but I got 1 and "" (empty)

Please, what I am missing?

Thanks!


回答1:


List := Clients.LockList;
try
  Clients.Add(Client); // <--- mistake here
finally
  Clients.UnlockList;
end;

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;

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.

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.

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.

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.


来源:https://stackoverflow.com/questions/27555342/threadlist-of-tobject-with-delphi-how-to-populate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!