我正在开发一个程序,用于从潜在的大目录结构及其许多文件结构(约100万个)中迁移文件。
我的迁移代码已经运行良好,并且我正在使用一个类来迭代目录结构,识别文件以依次依次迁移它们。
现在,我想更好地利用目标计算机的可用CPU资源,并进行那些迁移,以异步方式从System.Threading.TThreadPool
抓取线程来执行这些线程。
我对ITask
界面以及如何利用TTask
来设置一系列任务(它们将与一个TThreadPool
实例一起进行管理)非常了解。 br />
尽管设置了一个大的TArray<ITask>
数组,并在所有目录都经过时等待完成,但这似乎是一种不合适且效率低下的方法(尤其是在内存消耗方面)。
我认为我需要的只是一个简单的线程安全的 producer / consumer 队列,该队列随着工作线程可用于消耗任务的任务而增长和收缩,并完成它们。
现在,我在Emba文档中发现了一种听起来令人鼓舞的东西,称为TWorkStealingQueue
,但通常情况下,该文档非常贫乏,并且缺乏简洁的示例来说明如何使用它。
它会归结为类似的东西
TMigrationFileWalker = class(TFileWalker)
strict private
var
FPendingMigrationTasks : TArray<ITask>;
function createMigrationTask(const filename : string) : ITask;
strict protected
procedure onHandleFile(const filename : string); override;
public
procedure walkDirectoryTree(const startDir : string); override;
end;
implementation
procedure TMigrationFileWalker.onHandleFile(const filename : string);
var
migrationTask : ITask;
begin
migrationTask := createMigrationTask(filename);
self.FPendingMigrationTasks := self.FPendingMigrationTasks + [migrationTask];
migrationTask.Start();
end;
procedure walkDirectoryTree(const startDir : string);
begin
inherited walkDirectoryTree(startDir);
TTask.WaitForAll(self.FPendingMigrationTasks,SOME_REASONABLE_TIMEOUT);
end;
当然,我可以拥有一个线程安全的PC队列,并管理处理该线程的线程。但是,可以保证它可以与线程池一起使用,我想利用它附带的已经可用的负载平衡机制。
周围的人是否已经使用TWorkStealingQueue
,并且可以举一个简短的示例来说明如何在上述情况下使用它?或者至少要弄清楚该类的实际目的是什么,以防万一我从命名中完全误解了该类?
关于TWorkStealingQueue
的一项研究并没有比重定向到不足的Embarcadero文档更好的结果。