gpt4 book ai didi

multithreading - OmniThreadLibrary:如何检测所有递归调度(=池化)线程何时完成?

转载 作者:行者123 更新时间:2023-12-02 03:14:15 26 4
gpt4 key购买 nike

假设我必须在后台递归地迭代存储在树结构中的项目,并且我想使用线程池中的多个线程(每个“文件夹”节点一个线程)来遍历这棵树。我已经成功地使用 OmniThreadLibrary 提供的几种不同的低级和高级方法来实现这一点。

但是,我还没有弄清楚如何正确检测扫描是否已实际完成,即每个最后一个叶节点都已被处理。

我在网上找到了各种例子,要么检查GlobalThreadPool.CountExecuting + GlobalThreadPool.CountQueued <= 0或者使用 IOmniTaskGroup.WaitForAll() 。不幸的是,这些方法似乎都不适合我。支票始终返回 True太早了,即仍有一些任务正在运行时。不过,我看过的所有示例都没有使用递归 - 以及那些没有使用线程池的示例 - 这可能从一开始就不是一个好的组合?

这是一个(非常)简化的示例代码片段,说明我目前正在尝试执行此操作:

procedure CreateScanFolderTask(const AFolder: IFolder);
begin
CreateTask(ScanFolder)
.SetParameter('Folder', AFolder)
.Schedule();
end;

procedure ScanFolder(const ATask: IOmniTask);
var
lFolder,
lCurrentFolder: IFolder;
begin
if ATaks.CancellationToken.IsSignalled then Exit;

lCurrentFolder := ATask.Param['Folder'].AsInterface as IFolder;

DoSomethingWithItemsInFolder(lCurrentFolder.Items);

for lFolder in lCurrentFolder.Folders do
begin
if ATaks.CancellationToken.IsSignalled then Exit;
CreateScanFolderTask(lFolder);
end;
end;

begin
GlobalOmniThreadPool.MaxExecuting := 8;
CreateScanFolderTask(FRootFolder);

// ??? wait for recursive scan to finish

OutputResult();
end.

我尝试过的等待的一个示例实现是这样的(基于 example found on About.com ):

  while GlobalOmniThreadPool.CountExecuting + GlobalOmniThreadPool.CountQueued > 0 do
Application.ProcessMessages;

但这似乎总是在“根线程”完成后立即退出。即使我使用 Sleep() 添加人为延迟- 调用它仍然总是退出得太早。似乎在执行任务列表中删除的一个任务与在该任务内计划添加到排队任务列表中的任务之间存在“间隙”...

实际上,我非常愿意使用事件处理程序,而不是等待扫描完成(另外,我不想使用 Application.ProcessMessages 因为我在无表单应用程序中也需要它)并且我已经尝试过 IOmniTaskControl.OnTerminated并使用 TOmniEventMonitor但当这些任务为每一项已完成的任务触发时,我仍然需要检查当前任务是否是最后一项,这又归结为与上面相同的问题。

或者是否有更好的方法来创建可以避免此问题的任务?

最佳答案

一个简单的方法是自己统计“要处理的文件夹”。每增加一个值当您创建文件夹任务并在每次处理文件夹时递减它时。

var
counter: TOmniCounter;

counter.Value := 0;

procedure ScanFolder(const ATask: IOmniTask);
var
lFolder,
lCurrentFolder: IFolder;
begin
if ATaks.CancellationToken.IsSignalled then Exit;

lCurrentFolder := ATask.Param['Folder'].AsInterface as IFolder;

DoSomethingWithItemsInFolder(lCurrentFolder.Items);

for lFolder in lCurrentFolder.Folders do
begin
if ATaks.CancellationToken.IsSignalled then Exit;
counter.Increment;
CreateScanFolderTask(lFolder);
end;
counter.Decrement;
end;

关于multithreading - OmniThreadLibrary:如何检测所有递归调度(=池化)线程何时完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11137969/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com