mormot.core.threads--TSynBackgroundThreadMethod

海利鸟 2024-07-09 08:09:01 阅读 85

mormot.core.threads--TSynBackgroundThread

在mORMot 2框架中,<code>TSynBackgroundThreadEvent、TSynBackgroundThreadMethodTSynBackgroundThreadProcedureTSynBackgroundThreadProcessTSynBackgroundTimer这几个类虽然都涉及到后台线程的执行,但它们各自有不同的用途和设计目标。以下是对这些类之间差异的概述:

  1. TSynBackgroundThreadEvent

    • 这个类可能设计用于执行与事件相关的回调函数。它可能封装了一个事件处理机制,允许您在后台线程中响应特定的事件。
    • 回调函数的签名可能包括一个事件发送者(Sender)参数,以及可能的其他参数,用于传递事件相关的数据。
    • 由于名称中包含“Event”,它可能特别适用于事件驱动的场景。
  2. TSynBackgroundThreadMethod

    • 这个类设计用于执行标准的 TThreadMethod类型的回调,即无参数且返回 Void的过程。
    • 它提供了一种在后台线程中执行这些回调的简便方式,使得与Delphi标准线程库兼容的代码可以轻松地与mORMot 2框架集成。
    • 由于 TThreadMethod是Delphi中用于线程方法的标准类型,因此这个类可能特别适用于需要这种兼容性的场景。
  3. TSynBackgroundThreadProcedure

    • 这个类可能设计用于执行简单的无参数过程(procedure)回调,而不是一个对象方法或 TThreadMethod
    • 它与 TSynBackgroundThreadMethod类似,但可能更加专注于那些不需要传递额外参数的过程。
    • 使用这个类可以使代码更加简洁,特别是当回调不需要访问任何外部状态或参数时。
  4. TSynBackgroundThreadProcess

    • 这个类可能是一个更通用的后台线程处理类,它可能提供了执行周期性任务或长时间运行任务的能力。
    • 它可能封装了线程创建、启动、暂停、恢复和终止的逻辑,以及任务调度的机制。
    • 与其他几个类相比,TSynBackgroundThreadProcess可能更加灵活和强大,适用于需要复杂任务调度的场景。
  5. TSynBackgroundTimer

    • 这个类专门设计用于在后台线程中执行定时任务。
    • 它可能内部维护了一个或多个定时器,允许您安排任务在指定的时间间隔后执行。
    • TSynBackgroundTimer可能还提供了向定时任务传递消息或参数的能力,以及查询任务状态和执行结果的方法。
    • 它特别适用于需要定时执行任务的场景,如心跳检测、定时轮询等。

上述描述是基于对类名的一般性推断和假设。实际上,mORMot 2框架中的这些类的具体实现和用途可能有所不同。因此,如果您正在使用mORMot 2框架,并且想要了解这些类的确切差异和用法,最好的做法是查阅mORMot 2的官方文档或源代码。这将为您提供关于这些类的详细信息和示例代码,帮助您更好地理解和使用它们。

TSynBackgroundThreadMethodAbstrac 定义

/// TSynBackgroundThreadAbstract 进程的状态机状态

TSynBackgroundThreadProcessStep = (

flagIdle, // 空闲状态

flagStarted, // 已启动状态

flagFinished, // 已完成状态

flagDestroying); // 正在销毁状态

/// TSynBackgroundThreadAbstract进程的状态机状态集合

TSynBackgroundThreadProcessSteps = set of TSynBackgroundThreadProcessStep;

/// 抽象TThread类,能够在其自己的执行内容中运行一个方法

// - 典型用途是作为处理数据或远程访问的后台线程,

// 同时UI通过循环运行OnIdle事件保持响应:

// 例如,查看mormot.rest.client.pas单元中TRestClientUri.OnIdle是如何处理此事件的

// - 您不应直接使用此类,而应继承它并重写Process方法,

// 或者使用TSynBackgroundThreadEvent/TSynBackgroundThreadMethod,

// 并提供一个更加方便的回调函数

TSynBackgroundThreadMethodAbstract = class(TSynBackgroundThreadAbstract)

protected

fPendingProcessLock: TLightLock; // 对fPendingProcessFlag的原子访问

fCallerEvent: TSynEvent; // 调用者事件

fParam: pointer; // 参数指针

fCallerThreadID: TThreadID; // 调用者线程ID

fBackgroundException: Exception; // 后台线程异常

fOnIdle: TOnIdleSynBackgroundThread; // 空闲时回调事件

fOnBeforeProcess: TOnNotifyThread; // 处理前通知回调

fOnAfterProcess: TOnNotifyThread; // 处理后通知回调

fPendingProcessFlag: TSynBackgroundThreadProcessStep; // 待处理标志

procedure ExecuteLoop; override; // 重写执行循环

function OnIdleProcessNotify(var start: Int64): Int64; // 空闲处理通知,返回已用毫秒数

function GetOnIdleBackgroundThreadActive: boolean; // 获取OnIdle事件是否激活

function GetPendingProcess: TSynBackgroundThreadProcessStep; // 获取待处理状态

procedure SetPendingProcess(State: TSynBackgroundThreadProcessStep); // 设置待处理状态

// 如果获取成功则返回flagIdle,如果已终止则返回flagDestroying

function AcquireThread: TSynBackgroundThreadProcessStep;

procedure WaitForFinished(start: Int64; const onmainthreadidle: TNotifyEvent); // 等待完成

/// 当fProcessParams<>nil且fEvent被通知时,由Execute方法调用

procedure Process; virtual; abstract; // 抽象方法,需在子类中实现

public

/// 初始化线程

// - 如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回

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

constructor Create(const aOnIdle: TOnIdleSynBackgroundThread;

const aThreadName: RawUtf8;

const OnBeforeExecute: TOnNotifyThread = nil;

const OnAfterExecute: TOnNotifyThread = nil); reintroduce;

/// 销毁线程

destructor Destroy; override;

/// 在后台线程中异步启动Process抽象方法

// - 等待进程完成,同时调用OnIdle()回调

// - 在后台线程中引发的任何异常都将在调用者线程中转换

// - 如果self未设置,或者从当前正在处理的同一线程调用(以避免OnIdle()回调中的竞态条件),则返回false

// - 当后台进程完成时返回true

// - OpaqueParam将用于指定后台进程线程安全的内容

// - 此方法是线程安全的,即它将等待另一个线程已经启动的任何进程:

// 您可以从任何线程调用此方法,即使其主要用途是从主UI线程调用

function RunAndWait(OpaqueParam: pointer): boolean;

/// 设置一个回调事件,在远程阻塞过程期间循环执行,

// 例如,在长时间请求期间刷新UI

// - 您可以为此属性分配一个回调,例如调用Application.ProcessMessages,

// 以在后台线程中执行远程请求,但让UI仍然具有响应性:

// mORMotUILogin.pas中的TLoginForm.OnIdleProcess和OnIdleProcessForm方法将符合此属性的预期

// - 如果OnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回

property OnIdle: TOnIdleSynBackgroundThread read fOnIdle write fOnIdle;

/// 如果后台线程处于活动状态,并且在处理过程中调用了OnIdle事件,则为TRUE

// - 例如,用于确保没有来自用户界面消息的重新进入

property OnIdleBackgroundThreadActive: boolean read GetOnIdleBackgroundThreadActive;

/// 在Execute中每次处理之前触发的可选回调事件

property OnBeforeProcess: TOnNotifyThread read fOnBeforeProcess write fOnBeforeProcess;

/// 在Execute中每次处理之后触发的可选回调事件

property OnAfterProcess: TOnNotifyThread read fOnAfterProcess write fOnAfterProcess;

end;

TSynBackgroundThreadEvent,TSynBackgroundThreadMethod,TSynBackgroundThreadProcedure,TSynBackgroundThreadProcess

TSynBackgroundThreadEvent 定义

/// 由 TSynBackgroundThreadEvent 调用的后台进程方法

// - 当执行Process虚拟方法时,将提供RunAndWait()方法中指定的OpaqueParam参数

TOnProcessSynBackgroundThread = procedure(Sender: TSynBackgroundThreadEvent;

ProcessOpaqueParam: pointer) of object;

/// 允许后台线程处理方法回调

TSynBackgroundThreadEvent = class(TSynBackgroundThreadMethodAbstract)

protected

fOnProcess: TOnProcessSynBackgroundThread; // 回调事件

/// 仅调用OnProcess处理程序

procedure Process; override; // 重写Process方法

public

/// 初始化线程

// - 如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回

constructor Create(const aOnProcess: TOnProcessSynBackgroundThread;

const aOnIdle: TOnIdleSynBackgroundThread;

const aThreadName: RawUtf8); reintroduce; // 重引入构造函数

/// 提供一个方法处理程序,在后台线程中执行

// - 由RunAndWait()方法触发 - 该方法将等待直到完成

// - 这里将提供RunAndWait()方法中指定的OpaqueParam

property OnProcess: TOnProcessSynBackgroundThread

read fOnProcess write fOnProcess; // OnProcess属性,用于访问fOnProcess字段

end;

TSynBackgroundThreadMethod 定义

/// 允许后台线程处理可变的TThreadMethod回调

TSynBackgroundThreadMethod = class(TSynBackgroundThreadMethodAbstract)

protected

/// 仅调用RunAndWait()方法中提供的TThreadMethod

procedure Process; override; // 重写Process方法

public

/// 运行一次提供的TThreadMethod回调

// - 使用此方法,而不是继承的RunAndWait()

procedure RunAndWait(Method: TThreadMethod); reintroduce; // 重引入RunAndWait方法

end;

TSynBackgroundThreadProcedure 定义

/// 由 TSynBackgroundThreadProcedure 调用的后台进程过程

// - 当执行Process虚拟方法时,将提供RunAndWait()方法中指定的OpaqueParam参数

TOnProcessSynBackgroundThreadProc = procedure(ProcessOpaqueParam: pointer);

/// 允许后台线程处理过程回调

TSynBackgroundThreadProcedure = class(TSynBackgroundThreadMethodAbstract)

protected

fOnProcess: TOnProcessSynBackgroundThreadProc; // 回调过程

/// 仅调用OnProcess处理程序

procedure Process; override; // 重写Process方法

public

/// 初始化线程

// - 如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回

constructor Create(aOnProcess : TOnProcessSynBackgroundThreadProc;

const aOnIdle : TOnIdleSynBackgroundThread;

const aThreadName: RawUtf8); reintroduce; // 重引入构造函数

/// 提供一个过程处理程序,在后台线程中执行

// - 由RunAndWait()方法触发 - 该方法将等待直到完成

// - 这里将提供RunAndWait()方法中指定的OpaqueParam

property OnProcess: TOnProcessSynBackgroundThreadProc

read fOnProcess write fOnProcess; // OnProcess属性,用于访问fOnProcess字段

end;

TSynBackgroundThreadProcess 定义

type

// TSynBackgroundThreadProcess 类声明(稍后定义)

TSynBackgroundThreadProcess = class;

/// 由 TSynBackgroundThreadProcess 定期执行的事件回调

TOnSynBackgroundThreadProcess = procedure(Sender: TSynBackgroundThreadProcess) of object;

/// 能够以给定周期运行方法的 TThread 类

TSynBackgroundThreadProcess = class(TSynBackgroundThreadAbstract)

protected

fOnProcess: TOnSynBackgroundThreadProcess; // 定期执行的方法回调

fOnException: TNotifyEvent; // 当 OnProcess 引发异常时执行的事件回调

fOnProcessMS: cardinal; // 定期执行任务的时间间隔(毫秒)

fStats: TSynMonitor; // 处理统计信息

procedure ExecuteLoop; override; // 重写执行循环

public

/// 初始化线程以进行周期性任务处理

// - 当 ProcessEvent.SetEvent 被调用或自上次处理以来过去了 aOnProcessMS 毫秒时,将调用 aOnProcess

// - 如果 aOnProcessMS 为 0,则等待直到 ProcessEvent.SetEvent 被调用

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

constructor Create(

const aThreadName : RawUtf8;

const aOnProcess : TOnSynBackgroundThreadProcess;

aOnProcessMS : cardinal;

const aOnBeforeExecute: TOnNotifyThread = nil;

const aOnAfterExecute : TOnNotifyThread = nil;

aStats : TSynMonitorClass = nil;

CreateSuspended : boolean = false); reintroduce; virtual;

/// 终结线程并等待其结束

destructor Destroy; override;

/// 访问周期性任务的实现事件

property OnProcess: TOnSynBackgroundThreadProcess

read fOnProcess;

/// 当 OnProcess 引发异常时执行的事件回调

// - 提供的 Sender 参数是引发的异常实例

property OnException: TNotifyEvent

read fOnException write fOnException;

published

/// 访问周期性任务处理的延迟时间(毫秒)

property OnProcessMS: cardinal read fOnProcessMS write fOnProcessMS;

/// 处理统计信息

// - 如果在类构造函数中 aStats 为 nil,则可能为 nil

property Stats: TSynMonitor read fStats;

end;

TSynBackgroundThreadEvent 例程代码

uses

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

mormot.core.threads;

type

TMyProcessEvent = procedure(Sender: TObject; Param: Pointer) of object;

var

MyProcessEvent: TMyProcessEvent;

procedure MyBackgroundProcess(Sender: TObject; ProcessOpaqueParam: Pointer);

begin

// 这里是后台处理的代码

WriteLn('Background process running with param: ', Pointer(ProcessOpaqueParam)^);

// 假设我们传递了一个Integer指针作为OpaqueParam

Integer(ProcessOpaqueParam)^ := Integer(ProcessOpaqueParam)^ + 1;

end;

procedure InitializeAndRunBackgroundThreadEvent;

var

BGThread: TSynBackgroundThreadEvent;

Param: PInteger;

begin

New(Param);

Param^ := 10; // 初始化参数

MyProcessEvent := MyBackgroundProcess;

// 创建并启动后台线程事件

BGThread := TSynBackgroundThreadEvent.Create(

MyProcessEvent, // 传递我们的处理过程

nil, // OnIdle回调,这里不使用

'MyBackgroundThreadEventDemo'

);

try

// 运行后台线程并等待完成

BGThread.RunAndWait(Param);

WriteLn('Background process finished. New param value: ', Param^);

finally

BGThread.Free; // 销毁线程对象

Dispose(Param); // 释放参数内存

end;

end;

// 在程序的某个地方调用InitializeAndRunBackgroundThreadEvent

TSynBackgroundThreadMethod 例程代码

uses

SysUtils, Classes,

mormot.core.threads;

procedure MyThreadMethod(Thread: TThread);

begin

// 这里是线程方法的代码

WriteLn('Thread method running in background');

// 模拟一些耗时操作

Sleep(1000);

end;

procedure RunBackgroundThreadMethod;

var

BGThread: TSynBackgroundThreadMethod;

begin

// 创建后台线程方法对象

BGThread := TSynBackgroundThreadMethod.Create(nil, nil, 'MyBackgroundThreadMethodDemo');

try

// 注意:这里我们重写了RunAndWait方法,所以直接传递TThreadMethod

BGThread.RunAndWait(MyThreadMethod);

finally

BGThread.Free; // 销毁线程对象

end;

end;

// 在程序的某个地方调用RunBackgroundThreadMethod

注意:上面的 TSynBackgroundThreadMethod示例中,我假设了 RunAndWait方法被重写以接受 TThreadMethod作为参数,但根据原始定义,这并不是直接支持的。通常,您会在 Process方法内部调用传入的 TThreadMethod。为了保持示例简单,我展示了如何可能使用它,但在实际应用中,您可能需要在 Process方法内部处理这一点。

TSynBackgroundThreadProcedure 例程代码

uses

SysUtils, Classes,

mormot.core.threads;

procedure MyBackgroundProcedure(ProcessOpaqueParam: Pointer);

begin

// 这里是后台过程的代码

WriteLn('Background procedure running with param: ', Pointer(ProcessOpaqueParam)^);

// 假设我们传递了一个字符串指针作为OpaqueParam

WriteLn('String param: ', PString(ProcessOpaqueParam)^);

end;

procedure InitializeAndRunBackgroundThreadProcedure;

var

BGThread: TSynBackgroundThreadProcedure;

Param: PString;

begin

New(Param);

Param^ := 'Hello, Background!';

// 创建并启动后台线程过程

BGThread := TSynBackgroundThreadProcedure.Create(

MyBackgroundProcedure, // 传递我们的处理过程

nil, // OnIdle回调,这里不使用

'MyBackgroundThreadProcedureDemo'

);

try

// 运行后台线程并等待完成

BGThread.RunAndWait(Param);

finally

BGThread.Free; // 销毁线程对象

Dispose(Param); // 释放参数内存

end;

end;

// 在程序的某个地方调用InitializeAndRunBackgroundThreadProcedure

TSynBackgroundThreadProcess 例程代码

uses

SysUtils, Classes, // 引入SysUtils和Classes单元以使用WriteLn和TThread等

mormot.core.threads;

procedure MyProcessMethod(Sender: TSynBackgroundThreadProcess);

begin

WriteLn('Process method called in background thread.');

// 在这里执行您的后台处理逻辑

end;

var

BGThread: TSynBackgroundThreadProcess;

begin

try

// 创建TSynBackgroundThreadProcess实例

BGThread := TSynBackgroundThreadProcess.Create(

'MyBackgroundThread', // 线程名称

MyProcessMethod, // 周期性执行的方法

1000, // 周期时间,单位为毫秒

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

nil // OnAfterExecute回调,这里不使用

// aStats和其他参数根据需要进行设置

);

try

// 启动线程(注意:在TSynBackgroundThreadProcess的构造函数中,

// 如果CreateSuspended参数为false,则线程将自动启动)

// 在这个例子中,我们假设CreateSuspended默认为false

// 等待一段时间以观察后台线程的行为

// 注意:在实际应用中,您可能不需要这样做,因为主线程可能会继续执行其他任务

Sleep(5000); // 等待5秒

finally

// 销毁线程对象(注意:在析构函数中,线程将尝试优雅地终止)

BGThread.Free;

// 等待线程真正结束(可选,但在这个例子中我们依赖析构函数的行为)

end;

except

on E: Exception do

WriteLn('Error: ' + E.Message);

end;

WriteLn('Program ended.');

end.

注意:在上面的示例中,我假设 TSynBackgroundThreadProcess的构造函数有一个 CreateSuspended参数(这在标准的 TThread构造函数中是存在的),但根据您提供的类定义,这个参数实际上并没有在 TSynBackgroundThreadProcess的构造函数中明确列出。如果 TSynBackgroundThreadProcess是自动启动线程的,那么您可能不需要显式调用任何启动方法。

TSynBackgroundTimer 例程代码

uses

SysUtils, // 引入SysUtils单元以使用WriteLn

mormot.core.threads;

procedure MyTimerProcess(Sender: TSynBackgroundTimer; const Msg: RawUtf8);

begin

WriteLn('Timer process called in background thread. Message: ' + Msg);

// 在这里执行您的定时任务逻辑

end;

var

Timer: TSynBackgroundTimer;

begin

try

// 创建TSynBackgroundTimer实例

Timer := TSynBackgroundTimer.Create(

'MyBackgroundTimer' // 线程名称

// 其他参数根据需要进行设置,这里省略了OnBeforeExecute、OnAfterExecute、aStats和aLogClass

);

try

// 启用一个周期性任务,每2秒执行一次

Timer.Enable(@MyTimerProcess, 2);

// 向任务队列添加消息,并请求立即执行(尽管在这个上下文中,立即执行可能不会立即发生)

Timer.EnQueue(@MyTimerProcess, 'Hello from background timer!', true);

// 等待一段时间以观察后台定时器的行为

// 注意:在实际应用中,您可能不需要这样做,因为主线程可能会继续执行其他任务

Sleep(10000); // 等待10秒

// 禁用周期性任务(在这个示例中我们不会禁用它,但展示了如何禁用)

// Timer.Disable(@MyTimerProcess);

finally

// 销毁TSynBackgroundTimer实例(注意:在实际应用中,您可能希望等待所有后台任务完成后再销毁定时器)

// 但在这个简单示例中,我们立即销毁它

Timer.Free;

// 由于我们立即销毁了定时器,并且主线程继续执行(尽管在这个示例中被Sleep阻塞了),

// 因此后台线程可能没有机会执行更多的回调。

// 在实际应用中,您应该确保在销毁定时器之前给后台线程足够的时间来完成其工作。

end;

except

on E: Exception do

WriteLn('Error: ' + E.Message);

end;

WriteLn('Program ended.');

end.

在上面的 TSynBackgroundTimer示例中,我展示了如何创建定时器、启用周期性任务、向任务队列添加消息,并等待一段时间以观察定时器的行为。请注意,由于我们调用了 Sleep并且立即销毁了定时器,因此后台线程可能没有机会执行更多的回调。在实际应用中,您应该确保在销毁定时器之前给后台线程足够的时间来完成其工作,或者调用 Timer.WaitUntilNotProcessing(如果该类提供了这样的方法)来等待所有后台任务完成。然而,根据提供的类定义,TSynBackgroundTimer并没有直接提供 WaitUntilNotProcessing方法,所以您可能需要实现自己的同步机制来达到这个目的。



声明

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