PDFium Delphi Component Docs

FPdfAsync 유닛

유닛: FPdfAsync
VCL, LCL, FMX, 헤드리스 애플리케이션에서 반응성 있는 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과 메시지를 보존하는 취소 예외입니다
IPdfCancellationTokenIsCancelled 폴링, RegisterCallback, ThrowIfCancelled, 예외 지원을 갖춘 호환성용 워커 측 토큰입니다
IPdfCancellationTokenSourceToken과 멱등한 Cancel을 갖춘 호환성용 소유자 측 소스입니다
IPdfCancellationRegistrationId, IsRegistered, 스레드 안전한 Unregister를 갖춘 안정적인 콜백 등록입니다
IPdfCancellationTokenEx취소 메타데이터, 콜백 수, 제거 가능한 콜백 등록, 이벤트 기반 대기를 갖춘 확장 토큰입니다
IPdfCancellationTokenSourceEx원자적 TryCancel, CancelWithReason, 강력한 타입의 TokenEx를 갖춘 확장 소유자 소스입니다
TPdfCancellationTokenSourceNew, NewEx, NewTimeout으로 만드는 스레드 안전 소스 구현입니다
PdfNoCancellationToken취소되지 않는 공유 토큰으로, 취소 불가 작업을 위해 소스를 할당하지 않습니다

Future 타입

타입설명
TPdfFutureStatus결과 상태입니다. pfsSuccess, pfsCancelled, pfsFailure
TPdfFutureDispatchMode응답 정책입니다. pfdSynchronize는 응답을 메인 스레드에 게시하고, pfdWorkerThread는 워커에서 실행하며, pfdNone은 응답을 억제합니다
TPdfFutureOptions응답 디스패치와 워커 ThreadPriority를 위한 RunEx 설정입니다
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을 통해 기존 synchronized 응답 동작을 유지하고 RunEx로 구성 가능한 디스패치를 더하는 fire-and-forget 헬퍼입니다

Executor 타입

타입설명
TPdfAsyncPrioritypapLow부터 papCritical까지 네 개의 디큐 레인이며, 각 레인 안에서는 FIFO 순서를 유지합니다
TPdfAsyncTaskState작업 수명 주기입니다. patsQueued, patsRunning, patsSucceeded, patsCancelled, patsFailed
TPdfAsyncDispatchModepadWorkerThread, padSynchronize, 응답을 억제하는 padNone을 통한 응답 디스패치입니다
TPdfAsyncTaskWorker작업 취소 토큰을 받는 메서드 포인터 작업 항목입니다
TPdfAsyncTaskReply변경할 수 없는 작업 결과 스냅샷을 받는 메서드 포인터 완료 콜백입니다
TPdfAsyncTaskResultTaskId, State, Priority, QueuedAtTick, StartedAtTick, CompletedAtTick 타이밍, ErrorMessage와 ErrorClassName 워커 오류 쌍, 메시지를 동반한 CancellationReason, 격리된 ReplyErrorMessage를 담습니다
IPdfAsyncTaskCancel, 시간 초과를 지원하는 WaitFor, 원자적 Snapshot, Id, State, Priority, Token, IsCompleted 속성을 갖춘 제출된 작업 핸들입니다
TPdfAsyncExecutorStats용량, 현재 부하, 최대 큐 깊이, 누적 제출·성공·취소·실패·거부 수를 담습니다
EPdfAsyncQueueFull상한이 있는 큐가 작업을 더 받을 수 없을 때 Submit이 발생시킵니다
EPdfAsyncExecutorShutdownexecutor 종료가 시작된 뒤 Submit이 발생시킵니다
TPdfAsyncExecutor상한이 있는 큐, 네 개의 O(1) 우선순위 링, 협력적 작업 취소, 통계, 우아한 종료를 갖춘 재사용 가능한 고정 워커 풀입니다

시간 측정과 식별자 헬퍼

함수설명
PdfAsyncTickfuture와 executor 메타데이터가 사용하는 단조 증가 밀리초 틱을 반환합니다
PdfAsyncTickDelta방어적으로 경과 밀리초를 계산하며, 없거나 역전된 틱에는 0을 반환합니다
PdfNextAsyncIdfuture, 콜백 등록, executor 작업이 공유하는 프로세스 로컬 양수 ID를 반환합니다

취소 예제

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;

큐 용량에 상한이 있는 Executor 예제

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를 생성하면 워커 시작 전에 ENotSupportedException이 발생합니다

반복되거나 몰리는 작업에는 TPdfAsyncExecutor를 사용하세요. 작업이 연산마다 스레드를 하나씩 만드는 대신 고정된 스레드 집합을 재사용합니다

큐 용량을 양수로 두면 결정론적 백프레셔를 제공하고 0이면 큐가 무한해집니다. 실행 중인 작업은 큐 슬롯을 소비하지 않습니다

우선순위 스케줄링은 레인 사이에서는 엄격하고 레인 안에서는 FIFO이므로, papCritical과 papHigh는 실제로 지연에 민감한 작업을 위해 남겨 두세요

메인 스레드에서 호출하면 WaitForIdle이 synchronized 콜백을 처리하므로, padSynchronize 응답이 종료 교착 없이 마무리될 수 있습니다

각 시간 초과 소스는 취소나 만료까지 대기 스레드 하나를 가볍게 점유하므로, 아주 많은 수명 짧은 기한을 만든다면 공유 애플리케이션 타이머나 기한 스케줄러 쪽이 낫습니다

PDFium 객체 소유 규칙은 그대로 적용됩니다. 동시 워커마다 TPdf 인스턴스를 만들거나 분리하고, 같은 활성 문서 인스턴스를 동시에 변경하거나 렌더링하지 마세요

호환성

기존 IPdfCancellationToken, IPdfCancellationTokenSource, TPdfCancellationTokenSource.New, TPdfFuture<T>.Run API는 소스 수준 호환성을 유지합니다

구조화된 진단, 제거 가능한 콜백, 시간 초과 대기, 원자적 취소 소유권이 필요할 때만 확장 인터페이스를 사용하세요

콜백은 익명 메서드가 아니라 메서드 포인터이므로, 같은 API를 Delphi, C++Builder, Free Pascal에서 모두 컴파일할 수 있습니다

관련 항목

TPdf.RenderPageProgressive, TPdfView.AsyncRendering