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
或类似的解决方案更简单):
- 把工作推到一个
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, 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需要改进的地方,请发表评论。
我知道 TTask
并成功使用了 TTask.WaitForAll(array)
,还有 TParallel.&For()
。
但是现在想做一件看似简单的事情却不知道怎么做:
我收到了未知数量的商品,可能是数百万也可能只有几件,而且我事先并不知道。我如何在没有队列的情况下并行处理它们(大约 4 个线程左右)?如果 max threads 已经很忙,我想等待下一个空闲插槽。像 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, 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需要改进的地方,请发表评论。