如何解决Delphi TThreadPool:在继续执行代码之前等待空闲线程槽
我知道 TTask
并成功使用了 TTask.WaitForAll(array)
以及 TParallel.&For()
。
但现在我想做一件看似简单的事情,却不知道怎么做:
我收到了未知数量的商品,可能是数百万或只有几件,而且我事先不知道。我如何并行处理它们(大约 4 个线程左右),但没有队列?如果最大线程已经很忙,我想等待下一个空闲插槽。类似 TTask.Run()
之类的东西,在它真正开始运行之前不会返回。
我想我只是在监督一些简单的事情......?
当我完成时,我想等待所有剩余的任务完成。但当然,我不想在 WaitForAll()
的数组中包含数百万个。
我可以想象一个可能的解决方案(但我不喜欢它并希望使用 TTask
或类似的方法更简单):
- 将工作推送到
TThreadedQueue
,如果队列已满,它会自动让我等待 - 启动 4 个线程,让它们循环从该队列中弹出
我知道在某些情况下这可能是首选方式,但我的情况不会从中受益(例如重用任何对象、连接等)。
什么应该漂亮和干净的伪代码:
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,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 次执行,然后在开始处退出。
似乎默认线程池不能限制为少于处理器数量。
如果您认为有什么不好或可以/应该改进,请发表评论。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。