PDFium Component Docs

FPdfAsync Moduł

Unit: FPdfAsync
Infrastruktura anulowania, future i ograniczonej puli wątków roboczych dla responsywnego przetwarzania PDF w aplikacjach VCL, LCL, FMX i headless

Syntax

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;

Cancellation types

TypeDescription
TPdfCancellationReasonUstrukturyzowany powód zakończenia obejmujący żądania użytkownika, przekroczenia czasu, powiązaną pracę, zamknięcie, pracę zastąpioną i anulowanie zdefiniowane przez aplikację
EPdfOperationCancelledWyjątek anulowania z zachowanym oryginalnym Reason i komunikatem na potrzeby diagnostyki
IPdfCancellationTokenKompatybilny token strony roboczej z odpytywaniem IsCancelled, RegisterCallback, ThrowIfCancelled i obsługą wyjątków
IPdfCancellationTokenSourceKompatybilne źródło strony właściciela z Token i idempotentnym Cancel
IPdfCancellationRegistrationStabilna rejestracja wywołania zwrotnego z Id, IsRegistered i bezpiecznym wątkowo Unregister
IPdfCancellationTokenExRozszerzony token z metadanymi anulowania, licznikami wywołań zwrotnych, usuwalną rejestracją wywołań i oczekiwaniem opartym na zdarzeniach
IPdfCancellationTokenSourceExRozszerzone źródło właściciela z atomowym TryCancel, CancelWithReason i silnie typowanym TokenEx
TPdfCancellationTokenSourceBezpieczna wątkowo implementacja źródła tworzona przez New, NewEx lub NewTimeout
PdfNoCancellationTokenWspółdzielony token, który nigdy się nie anuluje i pozwala nie alokować źródła dla pracy, której nie można anulować

Future types

TypeDescription
TPdfFutureStatusStan wyniku: pfsSuccess, pfsCancelled lub pfsFailure
TPdfFutureDispatchModePolityka odpowiedzi: pfdSynchronize wysyła odpowiedź do wątku głównego, pfdWorkerThread wywołuje ją na wątku roboczym, a pfdNone wycisza odpowiedź
TPdfFutureOptionsUstawienia RunEx dla dystrybucji odpowiedzi i ThreadPriority wątku roboczego
TPdfFutureResult<T>Koperta ukończenia z Value i HasValue, Status, parą ErrorMessage i ErrorClassName, CancellationReason, OperationId, StartedAtTick i CompletedAtTick, pomocnikami statusu oraz ElapsedMilliseconds
TPdfFutureWorker<T>Wskaźnik metody roboczej, który otrzymuje token anulowania i zwraca wynik w tle
TPdfFutureReply<T>Wskaźnik metody wywołania zwrotnego otrzymujący ukończone TPdfFutureResult<T>
TPdfFutureThread<T>Typ wątku wsparcia kompilatora używany przez TPdfFuture<T>; konstruowany przez Create lub uwzględniające opcje CreateEx, a aplikacje normalnie wywołują Run lub RunEx
TPdfFuture<T>Pomocnik fire-and-forget, który przez Run zachowuje pierwotne zachowanie synchronizowanej odpowiedzi, a przez RunEx dodaje konfigurowalną dystrybucję

Executor types

TypeDescription
TPdfAsyncPriorityCztery tory pobierania od papLow do papCritical, z kolejnością FIFO wewnątrz każdego toru
TPdfAsyncTaskStateCykl życia zadania: patsQueued, patsRunning, patsSucceeded, patsCancelled lub patsFailed
TPdfAsyncDispatchModeDystrybucja odpowiedzi przez padWorkerThread, padSynchronize lub padNone, aby wyciszyć odpowiedź
TPdfAsyncTaskWorkerWskaźnik metody elementu pracy, który otrzymuje swój token anulowania zadania
TPdfAsyncTaskReplyWskaźnik metody wywołania ukończenia otrzymujący niemodyfikowalną migawkę wyniku zadania
TPdfAsyncTaskResultTaskId, State, Priority, czas QueuedAtTick, StartedAtTick i CompletedAtTick, para błędów roboczych ErrorMessage i ErrorClassName, CancellationReason z komunikatem oraz izolowany ReplyErrorMessage
IPdfAsyncTaskUchwyt zgłoszonego zadania z Cancel, uwzględniającym limit czasowy WaitFor, atomowym Snapshot oraz właściwościami Id, State, Priority, Token i IsCompleted
TPdfAsyncExecutorStatsPojemność, bieżące obciążenie, szczytowa głębokość kolejki oraz skumulowane liczniki zgłoszeń, sukcesów, anulowań, błędów i odrzuceń
EPdfAsyncQueueFullZgłaszany przez Submit, gdy ograniczona kolejka nie może przyjąć kolejnego zadania
EPdfAsyncExecutorShutdownZgłaszany przez Submit po rozpoczęciu zamknięcia egzekutora
TPdfAsyncExecutorWielokrotnego użytku stała pula wątków z ograniczoną kolejką, czterema pierścieniami priorytetów O(1), kooperatywnym anulowaniem zadań, statystykami i łagodnym zamknięciem

Timing and identity helpers

FunctionDescription
PdfAsyncTickZwraca monotoniczny tik w milisekundach używany przez metadane future i egzekutora
PdfAsyncTickDeltaWylicza defensywną wartość upływu czasu w milisekundach i zwraca zero dla tików brakujących lub wstecznych
PdfNextAsyncIdZwraca lokalny dla procesu dodatni identyfikator współdzielony przez future, rejestracje wywołań zwrotnych i zadania egzekutora

Cancellation example

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;

Bounded executor example

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;

Performance and threading

Kompilacje Delphi dla POSIX zachowują wartości opcji TThreadPriority tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest i tpTimeCritical dla zgodności ze źródłem, ale RTL platformy obsługuje wyłącznie domyślną ścieżkę planowania. tpNormal korzysta z tej ścieżki; skonstruowanie future z innym priorytetem wątku zgłasza ENotSupportedException przed uruchomieniem pracownika

Używaj TPdfAsyncExecutor dla pracy powtarzalnej lub skokowej, aby zadania korzystały ze stałego zestawu wątków zamiast tworzyć jeden wątek na operację

Dodatnia pojemność kolejki daje deterministyczne backpressure, a zero pozostawia kolejkę bez ograniczeń; uruchomione zadania nie zużywają miejsc w kolejce

Harmonogramowanie priorytetów jest ścisłe między torami i FIFO wewnątrz toru, więc rezerwuj papCritical i papHigh dla pracy naprawdę wrażliwej na opóźnienia

WaitForIdle obsługuje wywołania zsynchronizowane, gdy jest wywoływane z wątku głównego, co pozwala odpowiedziom padSynchronize się zakończyć bez zakleszczenia przy zamykaniu

Każde źródło limitu czasu posiada jeden lekki wątek oczekujący do momentu anulowania lub upływu terminu, więc przy tworzeniu bardzo dużej liczby krótkotrwałych terminów lepszy jest współdzielony czasomierz aplikacji albo harmonogram terminów

Reguły własności obiektów PDFium nadal obowiązują: twórz lub izoluj instancję TPdf na każdego współbieżnego pracownika i nie modyfikuj ani nie renderuj tej samej aktywnej instancji dokumentu współbieżnie

Compatibility

Pierwotne API IPdfCancellationToken, IPdfCancellationTokenSource, TPdfCancellationTokenSource.New i TPdfFuture<T>.Run pozostają zgodne na poziomie źródeł

Rozszerzonych interfejsów używaj tylko wtedy, gdy wymagana jest ustrukturyzowana diagnostyka, usuwalne wywołania zwrotne, oczekiwanie z limitem czasu lub atomowa własność anulowania

Wywołania zwrotne pozostają wskaźnikami metod, a nie metodami anonimowymi, więc to samo API kompiluje się w Delphi, C++Builderze i Free Pascalu

See Also

TPdf.RenderPageProgressive, TPdfView.AsyncRendering