PDFium Delphi Component Docs

FPdfAsync 單元

單元: FPdfAsync
為 VCL、LCL、FMX 與無 UI(headless)應用程式提供回應靈敏 PDF 處理所需的取消、future 與有界工作者集區基礎設施

語法

TPdfCancellationReason = (pcrNone, pcrUser, pcrTimeout, pcrLinked,
  pcrShutdown, pcrSuperseded, pcrOther);

IPdfCancellationTokenEx = interface(IPdfCancellationToken)
  function RegisterCallbackManaged(const ACallback: TThreadMethod): IPdfCancellationRegistration;
  function WaitForCancellation(ATimeoutMs: Cardinal): Boolean;
  property Reason: TPdfCancellationReason read GetReason;
  property CancellationMessage: string read GetCancellationMessage;
  property CancelledAtTick: UInt64 read GetCancelledAtTick;
  property CallbackCount: Integer read GetCallbackCount;
  property HasCallbacks: Boolean read GetHasCallbacks;
end;

IPdfCancellationTokenSourceEx = interface(IPdfCancellationTokenSource)
  function TryCancel: Boolean;
  function CancelWithReason(AReason: TPdfCancellationReason; const AMessage: string): Boolean;
  property TokenEx: IPdfCancellationTokenEx read GetTokenEx;
end;

TPdfCancellationTokenSource = class
  destructor Destroy; override;
  class function New: IPdfCancellationTokenSource; static;
  class function NewEx: IPdfCancellationTokenSourceEx; static;
  class function NewTimeout(AMilliseconds: Cardinal; const AMessage: string = ''): IPdfCancellationTokenSourceEx; static;
end;

TPdfFutureOptions = record
  DispatchMode: TPdfFutureDispatchMode;
  ThreadPriority: TThreadPriority;
  class function Default: TPdfFutureOptions; static;
end;

TPdfFuture<T> = class
  class procedure Run(const AWorker: TPdfFutureWorker<T>; const AReply: TPdfFutureReply<T>; const AToken: IPdfCancellationToken = nil); static;
  class procedure RunEx(const AWorker: TPdfFutureWorker<T>; const AReply: TPdfFutureReply<T>; const AToken: IPdfCancellationToken; const AOptions: TPdfFutureOptions); static;
end;

TPdfAsyncExecutor = class
  constructor Create(AWorkerCount: Integer; AQueueCapacity: Integer = 0);
  destructor Destroy; override;
  function Submit(const AWorker: TPdfAsyncTaskWorker; const AReply: TPdfAsyncTaskReply = nil; APriority: TPdfAsyncPriority = papNormal; ADispatchMode: TPdfAsyncDispatchMode = padWorkerThread): IPdfAsyncTask;
  function TrySubmit(const AWorker: TPdfAsyncTaskWorker; const AReply: TPdfAsyncTaskReply; out ATask: IPdfAsyncTask; APriority: TPdfAsyncPriority = papNormal; ADispatchMode: TPdfAsyncDispatchMode = padWorkerThread): Boolean;
  function WaitForIdle(ATimeoutMs: Cardinal): Boolean;
  function GetStats: TPdfAsyncExecutorStats;
  procedure Shutdown(ACancelPending: Boolean = True);
  property WorkerCount: Integer read FWorkerCount;
  property QueueCapacity: Integer read FQueueCapacity;
  property IsShutdown: Boolean read GetIsShutdown;
end;

TPdfAsyncExecutorStats = record
  WorkerCount: Integer;
  QueueCapacity: Integer;
  QueuedCount: Integer;
  RunningCount: Integer;
  PeakQueuedCount: Integer;
  SubmittedCount: Int64;
  SucceededCount: Int64;
  CancelledCount: Int64;
  FailedCount: Int64;
  RejectedCount: Int64;
end;

IPdfAsyncTask = interface
  function Cancel: Boolean;
  function WaitFor(ATimeoutMs: Cardinal): Boolean;
  function Snapshot: TPdfAsyncTaskResult;
  property Id: Int64 read GetId;
  property State: TPdfAsyncTaskState read GetState;
  property Priority: TPdfAsyncPriority read GetPriority;
  property Token: IPdfCancellationToken read GetToken;
  property IsCompleted: Boolean read GetIsCompleted;
end;

取消類型

類型說明
TPdfCancellationReason結構化的終止原因,涵蓋使用者要求、逾時、連結工作、關機、被取代的工作與應用程式自訂的取消
EPdfOperationCancelled取消例外,保留原始 Reason 與訊息以供診斷
IPdfCancellationToken相容的工作端權杖,支援 IsCancelled 輪詢、RegisterCallback、ThrowIfCancelled 與例外
IPdfCancellationTokenSource相容的擁有者端來源,含 Token 與等冪的 Cancel
IPdfCancellationRegistration穩定的回呼註冊,含 Id、IsRegistered 與執行緒安全的 Unregister
IPdfCancellationTokenEx擴充權杖,具取消中繼資料、回呼計數、可移除的回呼註冊,以及以事件為基礎的等待
IPdfCancellationTokenSourceEx擴充擁有者來源,具原子性 TryCancel、CancelWithReason 與強型別 TokenEx
TPdfCancellationTokenSource執行緒安全的來源實作,透過 New、NewEx 或 NewTimeout 建立
PdfNoCancellationToken永不取消的共用權杖,避免為不可取消的工作配置來源

Future 類型

類型說明
TPdfFutureStatus結果狀態:pfsSuccess、pfsCancelled 或 pfsFailure
TPdfFutureDispatchMode回覆政策:pfdSynchronize 將回覆遞交至主執行緒,pfdWorkerThread 在工作者上叫用,pfdNone 則抑制回覆
TPdfFutureOptionsRunEx 的回覆分派與工作者 ThreadPriority 設定
TPdfFutureResult<T>完成封套,含 Value 與 HasValue、Status、ErrorMessage 與 ErrorClassName 配對、CancellationReason、OperationId、StartedAtTick 與 CompletedAtTick、狀態輔助成員,以及 ElapsedMilliseconds
TPdfFutureWorker<T>方法指標型工作者,接收取消權杖並傳回背景結果
TPdfFutureReply<T>方法指標型回呼,接收完成的 TPdfFutureResult<T>
TPdfFutureThread<T>TPdfFuture<T> 使用的編譯器支援執行緒型別;透過 Create 或支援選項的 CreateEx 建構,應用程式通常呼叫 Run 或 RunEx
TPdfFuture<T>射後不理的輔助型別,透過 Run 保留原有的同步回覆行為,並透過 RunEx 加入可設定的分派

執行器類型

類型說明
TPdfAsyncPriority四條出列通道,從 papLow 到 papCritical,每條通道內部依 FIFO 順序
TPdfAsyncTaskState工作生命週期:patsQueued、patsRunning、patsSucceeded、patsCancelled 或 patsFailed
TPdfAsyncDispatchMode回覆分派方式:padWorkerThread、padSynchronize,或以 padNone 抑制回覆
TPdfAsyncTaskWorker方法指標型工作項目,接收所屬工作的取消權杖
TPdfAsyncTaskReply方法指標型完成回呼,接收不可變的工作結果快照
TPdfAsyncTaskResultTaskId、State、Priority、QueuedAtTick、StartedAtTick 與 CompletedAtTick 時序、ErrorMessage 與 ErrorClassName 工作者錯誤配對、連同訊息的 CancellationReason,以及隔離的 ReplyErrorMessage
IPdfAsyncTask已提交工作的控制代碼,含 Cancel、支援逾時的 WaitFor、原子性 Snapshot,以及 Id、State、Priority、Token 與 IsCompleted 屬性
TPdfAsyncExecutorStats容量、目前負載、佇列深度峰值,以及累計的已提交、成功、取消、失敗與拒絕計數
EPdfAsyncQueueFull當有界佇列無法再接受工作時由 Submit 引發
EPdfAsyncExecutorShutdown在執行器開始關閉後由 Submit 引發
TPdfAsyncExecutor可重複使用的固定工作者集區,具備有界佇列、四個 O(1) 優先權環、合作式工作取消、統計資訊與平滑關機

計時與識別輔助函式

函式說明
PdfAsyncTick傳回 future 與執行器中繼資料所使用的單調毫秒刻度
PdfAsyncTickDelta計算防禦性的經過毫秒數,遺失或逆轉的刻度會傳回零
PdfNextAsyncId傳回處理序本機的正整數 ID,由 future、回呼註冊與執行器工作共用

取消範例

var
  CancelSource: IPdfCancellationTokenSourceEx;
begin
  CancelSource := TPdfCancellationTokenSource.NewTimeout(5000, 'Export deadline exceeded');
  TPdfFuture<Integer>.Run(Worker, Completed, CancelSource.TokenEx);
  if UserRequestedCancel then
    CancelSource.CancelWithReason(pcrUser, 'Export cancelled by user');
end;

有界執行器範例

var
  Executor: TPdfAsyncExecutor;
  Task: IPdfAsyncTask;
begin
  Executor := TPdfAsyncExecutor.Create(4, 128);
  try
    if not Executor.TrySubmit(RenderPage, PageCompleted, Task, papHigh, padSynchronize) then
      HandleBackpressure;
    Executor.WaitForIdle(30000);
  finally
    Executor.Free;
  end;
end;

效能與執行緒

Delphi POSIX 建置保留 TThreadPriority 選項值 tpIdle、tpLowest、tpLower、tpNormal、tpHigher、tpHighest 與 tpTimeCritical,維持原始碼相容性,但平台 RTL 只支援預設排程路徑。tpNormal 使用該路徑;以其他執行緒優先權建立 Future,會在啟動 Worker 前拋出 ENotSupportedException

重複或突發性的工作請使用 TPdfAsyncExecutor,讓工作重用固定的一組執行緒,而不是每個操作都建立一條執行緒

正數的佇列容量提供確定性的背壓,零則表示佇列無上限;執行中的工作不佔用佇列槽位

優先權排程在通道之間是嚴格的,通道內部則為 FIFO,因此請將 papCritical 與 papHigh 保留給真正延遲敏感的工作

從主執行緒呼叫時,WaitForIdle 會處理同步回呼,讓 padSynchronize 回覆能夠完成而不發生關機死結

每個逾時來源在取消或到期之前都會持有一條輕量等待執行緒,因此需要建立大量短時限時,建議改用共用的應用程式計時器或期限排程器

PDFium 物件擁有權規則仍然適用:為每個並行工作者建立或隔離一個 TPdf 實體,並且不要並行修改或算繪同一個作用中文件實體

相容性

原有的 IPdfCancellationToken、IPdfCancellationTokenSource、TPdfCancellationTokenSource.New 與 TPdfFuture<T>.Run API 保持原始碼相容

只有當需要結構化診斷、可移除回呼、逾時等待或原子性取消擁有權時,才使用擴充介面

回呼仍使用方法指標而非匿名方法,因此相同的 API 可在 Delphi、C++Builder 與 Free Pascal 下編譯

另請參閱

TPdf.RenderPageProgressive, TPdfView.AsyncRendering