Search code examples
multithreadingdelphidelphi-2010waitformultipleobjects

How to increment the number of running threads dynamically and wait for them using a list?


I want to create a list of thread and change the number of running threads each interval of time ( depending on some condition), which is not possible using array of THandle because - as you know - here I need to fix the length of the array before creating threads, this is how I proceed:

procedure MainThread.execute;
var 
  HandleThread : THandle;
  ListOfThreadsH : TList;
begin
  ListOfThreadsH := TList.create;              
  while (condition) do
  begin
    HandleThread := TMyThread.Create( parameter1,..,parametern).Handle;
    ListOfThreadsH.add (HandleThread);
    ThreadCount := ThreadCount + 1;
  end;
  waitForMultipleObjects(ThreadCount, pointer(ListOfThreadsH), True, INFINITE);
end;

But, I'm having some issues with this:

  • Incompatible types pointer and cardinal in : ListOfThreadsH.add (HandleThread);, I can understand why I'm getting this but don't really know how to solve it.

  • Is it correct to wait for threads this way? Because as I know ListOfThreadsH type must be array of THandle. If not, how to wait for threads in this case?

If this is not the correct way to increment the number of running threads, then how to proceed? Thanks for your replies.


Solution

  • array of ... is dynamic, you can change its size at any time, eg:

    procedure MainThread.execute;
    var 
      ListOfThreads : TObjectList;
      ArrOfHandles : array of THandle;
      Thread : TMyThread;
    begin
      ListOfThreads := TObjectList.Create(True);
      try
        while (condition) do
        begin
          Thread := TMyThread.Create(...);
          ListOfThreads.Add(Thread);
          SetLength(ArrOfHandles, Length(ArrOfHandles) + 1);
          ArrOfHandles[High(ArrOfHandles)] := Thread.Handle;
        end;
        WaitForMultipleObjects(Length(ArrOfHandles), PWOHandleArray(Pointer(ArrOfHandles)), True, INFINITE);
      finally
        ListOfThreads.Free;
      end;
    end;
    

    Alternatively:

    procedure MainThread.execute;
    var 
      ListOfThreads : TObjectList;
      ListOfHandles : TList<THandle>;
      Thread : TMyThread;
    begin
      ListOfThreads := TObjectList.Create(True);
      try
        ListOfHandles := TList<THandle>.Create;
        try
          while (condition) do
          begin
            Thread := TMyThread.Create(...);
            ListOfThreads.Add(Thread);
            ListOfHandles.Add(Thread.Handle);
          end;
          WaitForMultipleObjects(ListOfHandles.Count, PWOHandleArray(Pointer(ListOfHandles.ToArray)), True, INFINITE);
        finally
          ListOfHandles.Free;
        end;
      finally
        ListOfThreads.Free;
      end;
    end;