mormot.core.threads--TSynParallelProcess

海利鸟 2024-07-09 08:09:02 阅读 54

mormot.core.threads--TSynParallelProcess

<code>{ ************ 线程池中的并行执行 }

type

/// TSynParallelProcess 的并行化过程回调

// - 如果 0<=IndexStart<=IndexStop,则应执行某些过程

TOnSynParallelProcess = procedure(IndexStart, IndexStop: integer) of object;

/// 为 TSynParallelProcess 执行过程的线程

TSynParallelProcessThread = class(TSynBackgroundThreadMethodAbstract)

protected

fMethod: TOnSynParallelProcess; // 回调方法

fIndexStart, fIndexStop: integer; // 要处理的索引范围

procedure Start(const Method: TOnSynParallelProcess; // 开始执行过程

IndexStart, IndexStop: integer);

/// 执行 fMethod(fIndexStart,fIndexStop)

procedure Process; override;

public

end;

/// 允许在线程池中并行执行基于索引的过程

// - 将创建自己的线程池,然后将工作分配给每个线程执行

TSynParallelProcess = class(TSynPersistentLock)

protected

fThreadName: RawUtf8; // 线程名称

fPool: array of TSynParallelProcessThread; // 线程池

fThreadPoolCount: integer; // 线程池中的线程数

fParallelRunCount: integer; // 并行运行次数

public

/// 初始化线程池

// - 您可以定义一些回调来嵌套线程执行,例如,分配给 TRestServer.BeginCurrentThread/EndCurrentThread

// - 最多可设置 MaxThreadPoolCount=32 个线程(您可以允许更大的值,但此线程池的目的是使其进程饱和每个 CPU 核心)

// - 如果 ThreadPoolCount 为 0,则不会创建线程,并且过程将在当前线程中执行

constructor Create(ThreadPoolCount: integer; const ThreadName: RawUtf8;

const OnBeforeExecute: TOnNotifyThread = nil; // 执行前通知回调

const OnAfterExecute: TOnNotifyThread = nil; // 执行后通知回调

MaxThreadPoolCount: integer = 32); reintroduce; virtual;

/// 终结线程池

destructor Destroy; override;

/// 并行运行一个方法,并等待执行完成

// - 将 Method[0..MethodCount-1] 的执行分散到线程中

// - 如果在过程中发生任何异常,则此方法将引发 ESynParallel 异常

// - 如果设置了 OnMainThreadIdle,则当前线程(例如,预期为主 UI 线程)将不会处理任何内容,但在等待后台线程时调用此事件

procedure ParallelRunAndWait(const Method: TOnSynParallelProcess;

MethodCount: integer; const OnMainThreadIdle: TNotifyEvent = nil);

published

/// 已激活的线程数

property ParallelRunCount: integer

read fParallelRunCount;

/// 此实例线程池中当前有多少线程

property ThreadPoolCount: integer

read fThreadPoolCount;

/// 一些文本标识符,用于区分每个拥有的线程

property ThreadName: RawUtf8

read fThreadName;

end;

后期再整理!

由于 TSynParallelProcess在mORMot 2框架中是一个假定的类(因为标准的mORMot 2库并不直接包含这个类名,但它可能是一个自定义扩展或类似功能的类的代表),我将基于您提供的类定义来编写一个假设的例程代码,这个代码将模拟在Free Pascal中使用这样一个类。

请注意,以下代码将不会直接编译,因为 TSynParallelProcessTSynParallelProcessThread的具体实现细节(如构造函数、析构函数和方法的内部逻辑)并未给出。但是,我将提供一个结构化的示例,展示如何使用这样的类(如果它存在的话)。

program TSynParallelProcessDemo;

{$MODE DELPHI}

uses

SysUtils, Classes; // 引入必要的单元

// 假设TSynParallelProcess和TSynParallelProcessThread已经在某个单元中定义

// 这里我们使用一个占位符单元名YourMormotUnit

// 注意:在实际应用中,您需要替换'YourMormotUnit'为包含这些类的实际单元名

uses YourMormotUnit;

procedure MyParallelTask(IndexStart, IndexStop: integer);

begin

// 这里是您的并行任务逻辑

WriteLn('Executing task with indices from ', IndexStart, ' to ', IndexStop);

// 模拟耗时操作

Sleep(100); // 假设每个任务需要一些时间来完成

end;

var

ParallelProcessor: TSynParallelProcess;

TaskCount: Integer;

begin

try

// 初始化任务计数(这里假设我们有100个任务要并行处理)

// 注意:在实际应用中,您可能需要根据具体情况来确定这个值

TaskCount := 100;

// 创建TSynParallelProcess实例

// 注意:这里我们假设ThreadPoolCount是一个合理的值,例如CPU核心数的两倍

// 并且MaxThreadPoolCount足够大以容纳所需的线程数

// ThreadName是可选的,用于标识线程池中的线程

ParallelProcessor := TSynParallelProcess.Create(

System.SysUtils.GetProcessorCount * 2, // 假设线程池大小为CPU核心数的两倍

'MyParallelTasks', // 线程名称前缀(可选)

nil, // OnBeforeExecute回调(这里不使用)

nil // OnAfterExecute回调(这里不使用)

);

try

// 并行运行任务并等待完成

// 注意:这里的ParallelRunAndWait是假设的方法,它可能不直接存在于TSynParallelProcess中

// 您需要根据实际的方法签名和逻辑来调整以下调用

// 由于我们没有ParallelRunAndWait的具体实现,这里只是一个示意性的调用

// 在实际中,您可能需要调用一个不同的方法,或者ParallelRunAndWait本身就需要您来实现

// 假设ParallelRunAndWait接受一个任务过程和任务总数作为参数

ParallelProcessor.ParallelRunAndWait(

@MyParallelTask, // 指向您的并行任务过程的指针

TaskCount // 要并行处理的任务总数

);

finally

// 销毁TSynParallelProcess实例

ParallelProcessor.Free;

end;

except

on E: Exception do

WriteLn('An error occurred: ', E.Message);

end;

// 保持控制台窗口打开,直到用户按任意键

WriteLn('Press Enter to exit...');

ReadLn;

end.

重要说明

  1. 类和方法的存在性:上述代码假设 TSynParallelProcess类及其 ParallelRunAndWait方法存在。在mORMot 2的标准库中,这样的类和方法可能不存在,或者它们的名称和参数可能有所不同。
  2. 实现细节:由于我们没有 TSynParallelProcessTSynParallelProcessThread的具体实现,因此上述代码中的 ParallelRunAndWait调用是示意性的。在实际应用中,您需要根据实际可用的方法来实现并行任务的执行。
  3. 线程池大小:在创建 TSynParallelProcess实例时,我使用了 System.SysUtils.GetProcessorCount * 2作为线程池的大小。这只是一个常见的启发式方法,用于确定合理的线程数。然而,最佳线程数取决于您的具体应用程序和工作负载。
  4. 错误处理:代码中包含了基本的错误处理逻辑,用于捕获并打印异常消息。在实际应用中,您可能需要根据需要扩展这种错误处理。
  5. 单元引用:请将 uses YourMormotUnit;中的 YourMormotUnit替换为包含 TSynParallelProcessTSynParallelProcessThread定义的实际单元名。如果这些类是您自定义的,那么您需要确保它们已经被正确编译并包含在您的项目中。


声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。