1、Controller MVC架構中的控制層,在SpringMVC中,由 Handler 組成 負責提供訪問應用程式的行為:處理用戶的請求並調用 Model層 將其轉換為一個模型數據跳向 View層 在Spring MVC中,對於Controller的配置方式有很多種,通常可以通過介面定義或註解定 ...
mormot.core.threads--TSynBackgroundThread
在mORMot 2框架中,TSynBackgroundThreadEvent
、TSynBackgroundThreadMethod
、TSynBackgroundThreadProcedure
、TSynBackgroundThreadProcess
和TSynBackgroundTimer
這幾個類雖然都涉及到後臺線程的執行,但它們各自有不同的用途和設計目標。以下是對這些類之間差異的概述:
-
TSynBackgroundThreadEvent:
- 這個類可能設計用於執行與事件相關的回調函數。它可能封裝了一個事件處理機制,允許您在後臺線程中響應特定的事件。
- 回調函數的簽名可能包括一個事件發送者(Sender)參數,以及可能的其他參數,用於傳遞事件相關的數據。
- 由於名稱中包含“Event”,它可能特別適用於事件驅動的場景。
-
TSynBackgroundThreadMethod:
- 這個類設計用於執行標準的
TThreadMethod
類型的回調,即無參數且返回Void
的過程。 - 它提供了一種在後臺線程中執行這些回調的簡便方式,使得與Delphi標準線程庫相容的代碼可以輕鬆地與mORMot 2框架集成。
- 由於
TThreadMethod
是Delphi中用於線程方法的標準類型,因此這個類可能特別適用於需要這種相容性的場景。
- 這個類設計用於執行標準的
-
TSynBackgroundThreadProcedure:
- 這個類可能設計用於執行簡單的無參數過程(
procedure
)回調,而不是一個對象方法或TThreadMethod
。 - 它與
TSynBackgroundThreadMethod
類似,但可能更加專註於那些不需要傳遞額外參數的過程。 - 使用這個類可以使代碼更加簡潔,特別是當回調不需要訪問任何外部狀態或參數時。
- 這個類可能設計用於執行簡單的無參數過程(
-
TSynBackgroundThreadProcess:
- 這個類可能是一個更通用的後臺線程處理類,它可能提供了執行周期性任務或長時間運行任務的能力。
- 它可能封裝了線程創建、啟動、暫停、恢復和終止的邏輯,以及任務調度的機制。
- 與其他幾個類相比,
TSynBackgroundThreadProcess
可能更加靈活和強大,適用於需要複雜任務調度的場景。
-
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
方法,所以您可能需要實現自己的同步機制來達到這個目的。