Delphi TThreadPool:在继续执行代码之前等待空闲线程槽

Delphi TThreadPool: wait for free thread slot before proceeding with code

我知道 TTask 并成功使用了 TTask.WaitForAll(array),还有 TParallel.&For()

但是现在想做一件看似简单的事情却不知道怎么做:

我收到了未知数量的商品,可能是数百万也可能只有几件,而且我事先并不知道。我如何在没有队列的情况下并行处理它们(大约 4 个线程左右)?如果 max threads 已经很忙,我想等待下一个空闲插槽。像 TTask.Run() 这样的东西,直到它真正开始 运行.

才会回来

我想我只是在监督一些简单的事情......?

完成后,我想等待所有剩余任务完成。但是我当然不想在 WaitForAll().

的数组中有数百万个

我可以想象一个可能的解决方案(但我不喜欢它,希望使用 TTask 或类似的解决方案更简单):

我知道在某些情况下这可能是首选方式,但我的情况不会从中获益(比如重用任何对象、连接等)。


的伪代码:

MyThreadPool:= TMyThreadPool.Create(4);
while GetNextItem(out Item) do
  //the following comes back when it has really been started:
  MyThreadPool.Run(procedure begin Work(Item); end);
MyThreadPool.WaitFor;

这似乎是一个可行的解决方案,但滥用 TParallel.&For 可能不是很好。我仍然希望得到更好的答案。

if FindFirst(Path, 0, SearchRec) = 0 then
  try
    TParallel.&For(0, 99999,
      procedure(I: Integer; LoopState: TParallel.TLoopState)
      var
        Filename: string;
      begin
        if LoopState.ShouldExit then Exit;

        TMonitor.Enter(Self);
        try
          Filename:= SearchRec.Name;
          if (FindNext(SearchRec) <> 0) or TThread.CheckTerminated then
            LoopState.Stop; //or .Break?
        finally
          TMonitor.Exit(Self);
        end;

        try
          ProcessFile(Filename);
        except
          on E: Exception do Log(E.ToString); //maybe also want to Stop
        end;
      end);
  finally
    FindClose(SearchRec);
  end;

我写了很多跟踪日志,看起来不错。唯一不好的是,在最后一个文件之后,它仍然开始执行 10-20 次以上的执行,然后在开始时退出。

默认的线程池似乎也不能限制在少于处理器的数量。

如果您认为有什么不好的地方或can/should需要改进的地方,请发表评论。