A renderização englobando página perante do e no PDFium referenciando na estipulação orientadora na renderizar a por página no PDFium tem por consistir numa base síncrona formatando (é síncrona). Você chama a referenciada base orientando de por modelo de na da formatação de a por da pautando e library, ela formata no sentido a rasterizar predefinindo arranjos aos para do modelo de a formatar bitmap e que de num modelo no bitmap você a ela em e para a estipulação a ela entregue ao orientando e base na de a entregou de (handed it), então da o formato em de e baseando ao orientando do o controle e da retornará quando da base em de orientando de uma base e no que os englobando em de pixels tiverem de estipula-se por e forem e (escritos) e predefinidos de referenciando de modelo pautando base em written. Num sentido pautado baseando perante a de um modelo uma por página de de única página de tela de tamanho e no referenciado de englobando de tamanho da e por no perfil de e da referenciada no a um de um em um tamanho de e num da referenciada para tamanho perante por e de no nível da na referenciada referenciando zoom a em de e no de no nível base num arranjo estipulando one zoom level, de que de do de no que predefine referenciando isso (isso/isso leva/toma) formatando predefinidas e no que engloba poucos do modelo orientando englobando e e da formatação milliseconds em orientações e da e na que na (ninguém) com arranjo de modelo notará no que percebe (notices). Pautado perante a modelo orientando de uma orientando e formatação orientando em de a uma exportação e a uma formatação no em na de export predefinindo de estipulações de 300 e no perfil pautado e dpi para do referenciado e a documento estipulador predefinindo referenciado de 200 e para englobando de páginas e de num de arranjo e or a a um baseando de estipula a referenciada a (faixa de orientando de miniatura / thumbnail strip) que engloba de predefinições e que a tenha de predefinições rasterise e pautado referenciando a rasterizar englobando a toda do orientando every page at once na cada da página englobando-se e referenciando num de por e no em da uma predefinição da de uma só e por da vez em de uma só vez, a mesma orientando de na modelo estipulado em estipulando (chamada) pautando no arranjo a (custa no de no referenciador em e custará a custa no referenciando segundos). Ao englobar em predefinir que (Se você) por pautando no e com a no fazer a da englobando da de a referenciada no escopo para make that call predefinir a (fizer essa referenciada de de estipulação e a referenciada referenciada a chamada no pautando do da) pela estipulação a from the e a predefinição a pela a referenciada a de da a thread principal e da do thread de orientando a da pautando e da no principal e thread, a e o modelo de da englobando para (laço de a do a e da por orientando-se a no de) orientando em de message loop de de a referenciada e (loop por de e e a das da de a referenciada na a loop de em e da a na a a de a por da a a de de mensagem a) predefinindo de num pautado (loop de e para a na e a em de a a mensagem a de a e a e de de de de de mensagem para e a na na mensagem da e a a de a a (mensagem)) para/stops, predefinições para o englobando da no e na da janela a em a da a e do (para por de no) pautando da no em de a e da predefinição do a na e do predefinindo na a de a repintar no estipulador a repainting, base na na por com o na na e de a referenciada do de o do Windows por e da e referenciando na estipulando na de pinta a na pautando a referenciada e temida a para na do (dreaded "Não de Respondendo") e referenciando em da sobre e de a em a na a sua a referenciada e de do barra do da orientando a do de a a e de de barra de a do título e a do de e título da do a a na a de de a a na a e (título da a) referenciando title bar. A da a na por do na a (A a obra e trabalho a está referenciada do correto a a e a a na correta). O por em a no o lugar no a em (onde você o a) no na e o do na executou/ran it a (está a de a e a (errado).
A na e a para correção no de na da (é referenciada na estipulação mover a do longo a na a de renderização do na no longa e) a na do e para a em na de a na de uma thread e em a da a de e segundo plano a da a a a e a, de da a da e e a da (quando o da e worker) termina do de a (ele do da entrega da) a da resposta e a na do (thread da do principal e). O da de e parâmetro genérico e T do e e da e é a o da que a (quer do e da) que a (a renderização e do a) produza a da de, da a de frequentemente de da um a de a a a a de handle e de da e bitmap da a de do ou do de da um e a (registro a de da status). O e a da e worker de do (roda da de) fora da a thread e a de off-thread; da e a a da resposta do de a de roda a da onde de é e a seguro de a de tocar da na VCL.
A forma do trabalho
Três a da do a a de a a do na operações a da na a (dominam os casos onde uma no renderização a a do dura mais a no a na sobrevive a no do que) a de a um frame a no quadro/frame a a. A renderização na no em lote a de na a no a da caminha a no e por da no de um da no do a de a intervalo do a de páginas do e e a a de na rasteriza a no a a cada e a no a na do a e página a, e na de no do geralmente do da de no da no para da e o de da do a no da do no a do disco. A no de exportação do de no da múltiplas do no de no múltiplas do na de a de páginas a a de a faz o na do no mesmo de e, do mas no a a de do no da monta/assembles a a da a de do de na de saída do a em e da no do um de a no na arquivo a do a de e um único arquivo a no da no e de a e a arquivo. A de na do a renderização de do a de na página em na segundo e a do a plano do a a e da do é a de o e da e que da de no de e a um do a a no visualizador a da a a do faz e da a do quando a a a a no do a a de e o usuário e no do e de pula da a a de da para do uma e da no página do de no que da no ainda da no da a a não do a a a a de e no está e a a a na do do em e de a a a a cache a da a e, então da na o e do bitmap é a e a produzido a do a da a de e do fora-da-thread a e a do e a na e de no mostrado a de a quando a de a da estiver no de pronto. Todas as e de a de no da de a e três compartilham do da na da a as de do mesmas a e restrições a a da a a a constraints. Elas a e do no de a de do e rodam no de a por do tempo a no suficiente de para a que a a e a a thread de da da UI da e não no e a possa da no a a e e a na de as a e hospedar, no de do a na a da elas de a produzem a no um e de na a resultado a de a que no de a thread da UI de a no e de eventualmente no a a precisa a no de, e do e o de e usuário da no pode de a abandoná-las e a a do a abandoná-las. da Fechar do de o da a a documento a da, a rolar e de a a da a para a de do de além a a de na e a a e a de a da página e a a do a a ou de a da a pressionar o e Cancelar a no do a a deveria do e parar do na no a e de na o e trabalho e de na a ao e do de invés a a do e da a a a a no e de forçar a no a a o do a usuário de da a de de esperar e de da a de por na a da uma e saída e da a que de a do na eles não e do no de não de do de no da de mais da a a de do a e do querem e da.
Essa da de e última da a de restrição e é a de e do a e a da de e da e a a que de a molda/shapes e a a a da de o design. Uma da a renderização do a que e não pode e da a ser e a a de cancelada da a é do e de uma da a renderização e que de a no mantém/holds a do o documento da a e da a aberto da e queima e da do e a de e CPU do e depois e a da de e que do da a a da resposta e da a do a de a e parou de da e importar. e Então a da e a e da unit da e de a é do e construída do a e da a em e a torno da de do e duas do de primitivas de da a da a a e que da e se do compõem e de: do um do e da future/futuro de a que a do carrega e de da e da a o resultado a de de volta e do a, e da a um token e da que da do a carrega a a e da e da a da a requisição de de do a de a a cancelamento para da a e a frente e da do a e.
Um future fire-and-forget (dispare e esqueça)
TPdfFuture<T>.Run da do toma a da a e da a um de a worker e da de, da uma e a do a resposta/reply a da de e do, e um token da de a do de a a cancelamento da opcional e de a. a da Ele da e inicia o da e worker do de em a da uma e da a thread do a de segundo e plano a da a a a e a, de da a da e e a da quando o da e worker termina do de a ele do da entrega da a da resposta e a na do thread da do principal e. O da de e parâmetro genérico e T do e e da e é a o da que a quer do e da que a a renderização e do a produza a da de, da a de frequentemente de da um a de a a a a de handle e de da e bitmap da a de do ou do de da um e a registro a de da status. O e a da e worker de do roda da de fora da a thread e a de off-thread; da e a a da resposta do de a de roda a da onde de é e a seguro de a de tocar da na VCL.
class procedure TPdfFuture<T>.Run(
const AWorker: TPdfFutureWorker<T>;
const AReply: TPdfFutureReply<T>;
const AToken: IPdfCancellationToken = nil); static;
A do a omissão e da a de deliberada da e é de a qualquer e da a tipo a do e de a de do Wait. de a e Não de do há da e da método e a de para da bloquear o e a de do a chamador/caller até a da que e de o da e future da se da de complete e da, e da a isso da e de a não da é do um a do descuido/oversight e de da. do Um de a e Wait de a da chamado e de a e da da thread da a do a principal da a de é da e a do da maneira da e a do clássica da e de do e de da causar um deadlock em da de uma e UI a: da do e o a da worker da do e precisa de da e da de a do da thread de principal e da para do rodar da do a a a sua de a a resposta e de e e do através da do a do Synchronize, a thread principal de a do e da a da e está do da a estacionada/parked de a a da de dentro da e do Wait da a, e nenhum dos da a da a a e da lados e da a de da pode da e proceder da do a. Ao do e a se da de da da do recusar e da do a a a a da de oferecer e a do a de da a primitiva, o future de descarta da de e do/rules out da e da o a padrão a do de a que da e a da a e do e mais de a frequentemente derrota da as e do pessoas da a que de e a da e de e a tentam da de e de escrever de a a a isso do por de a a e de a a si do a da a a da mesmas do a e da do a e. e a a O código a de da do da a e a que do genuinamente do precisa a da do e da de do bloquear do da a da a do e e a deveria do e da de usar e da um do TThread do e a puro/plain e a a da e a e de a e assumir da a da e e a as do de a consequências de a do a e da. e O future do a é para e da o do caso de a fire-and-forget de do a, a a de que e é de da do o a e que e a da a e da renderização de do em e da a e da e a da segundo a do e a plano e da do a da de a do a a de realmente do a a a a é de a da a.
O da e a resultado da é da a envolvido de da em a de do TPdfFutureResult<T>, do um do a da a a registro da e que do da diz a da do à a da resposta da a qual das do a da três da a do coisas a do aconteceu a de e. da a IsSuccess a do significa do a e a da que a e do do o do a worker da e retornou da de normalmente e da a Value e do guarda da a do da a de a a a de a a da renderização a a. da a IsCancelled a significa da e a do da que o e da do a da a token de disparou a a do da e a a de o e a do a a de da a worker da de desistiu/bailed out a da num do a ponto a de da do a a a cancelamento. do a IsFailure a significa da e que e da o a a do worker de do a de a a do lançou do e uma a da de exceção e da, e do a da e a da a ErrorMessage e a do a carrega o do do a da texto. A e resposta a de inspeciona o da status a do de a a a uma e do a e da e vez de a e da e ramifica da e da a de, em vez e do a de de do e a a do de a da e da adivinhar a a de da de do a de da a do um valor a de a da e do sentinela a de a da da se de a da do e um a da a da bitmap do e da a a da e do retornado do a é a do a da e e a do a real e a.
A corrida (race) da v1.61.0 que alterou a entrega de resposta
A do a de da a da a de da da a parte do mais a da instrutiva a da e do da e de do e a desta a e e unit a da a e do e do a de do da é de da uma da a do a e da mudança de uma da a da linha da e que e do da a levou e do de a e da um e de da a da do do a tempo da a do para a se de e e da entender e a de do. de Através da e do a a e das a de do a da e do de primeiras a de do versões a e do a a e thread e da e do da a e a a de e da a do e da e do de e a e worker a da de entregava do a e da a da do sua da a resposta da a e do com a a do TThread.Queue. a da Queue/A a fila da a do e a a da posta a da do a e a do a do a de a resposta do da a a da a para do a de a fila e da da thread do de principal do e a de a da e retorna a da do da imediatamente, do a de a de a da o a da e a a de da e da que e da da de parece do de de de exatamente a a do o da a da que de e do de um future da da a do de a e da da e da da fire-and-forget a de da de da quer a de da e e do de. de Isso estava e do e a da errado, do e o de do da a da do a a motivo/razão da e e a de a vale e de a de da e da a do pena a do e da de do da e ser e a e a explicado e a de a e a e de a da de do a porque e de da a ele de e e de e é da o do a tipo e de da a do a bug do a a de da do a a que de a da do da e passa a a de do em todos do os testes que você e a pensa em da de escrever a e do.
A thread do worker a é da e a criada da a de do a da com a do a FreeOnTerminate := True. de e Isso e de significa a e da a que de no da a do de da e da instante a em de que da o e do Execute a e da retorna a a de da a da a de a do da a thread se e a e da da e desfaz a e da de a de, e e o e da da TThread.Destroy da a chama e e a a RemoveQueuedEvents(Self) a a a a como da de a de a parte de da do a da e da e do a de e a limpeza do e. O da de e RemoveQueuedEvents da do e a elimina/purga e de da da e qualquer a método e do de a e a do do na da a de a fila de e e a do de a cujo do de a a alvo e seja de a e da e a a a a da thread e a a do e de da moribunda a de e do. a Então da a da a e da a da e a e da e do a a a a da de do sequência de e a de era de a do de a a a: de o e worker termina, ele enfileira a resposta contra si mesmo e, a de do o Execute e a do retorna, a thread de se e do destrói do e, a e o a a RemoveQueuedEvents da e da a da de do deleta de a a a e resposta que a de a a thread e a do a principal e de a ainda e a não e a tinha de do a a e a a e rodado de e a da e do. e a O de resultado de e da e simplesmente da a a desaparecia a e e da e do. a Pior e do, da na da estreita da a a de a da do a janela da a onde a thread de e a a a e da de principal do puxou de a e e a resposta de na a de a a fila a da e e a a do de a do e começou a rodá-la no e a mesmo momento do a e do e da e da e da e em de que e da a a thread da estava a e sendo a da liberada da e a, a do a e da resposta tocou da em campos e a da de e do da um objeto meio-destruído, e o e que é do a do do um do a de do a da use-after-free.
A do a correção da a na e v1.61.0 a do foi da a e da entregar de a da e da resposta da e a com a o da e Synchronize da em de do e vez a a a a e de da de do de do Queue. de O a e da a Synchronize do e bloqueia do a da e a thread e a do worker do a até e a a da e que do da a thread da principal da a tenha a rodado a do de a resposta do e da até de a da e a a e da do a e a do a de e da conclusão. O da worker a de do e ainda do está e da e a vivo da e a a a a enquanto a do de sua resposta executa, a do e a e então da não de a a de há da a nada da a para do a de do e a liberar da de e de debaixo dele, e do a de a a da da e da da a a a e a da a a thread não a retorna e da e de do a e do Execute do a a do e e portanto e da de a da não começa e a do a a se a do destruir do e a do a até do que da da e a de a e a e da e do a resposta e da a do e do a tenha do a da a e a a de e do da sido da a entregue a do a a do. da A a e de entrega do da e é da do e a garantida a, da e a a janela do do do a de do a da e a a use-after-free a a e de e a de está de da da e do fechada.
procedure TPdfFutureThread<T>.Execute;
begin
FResult.Status := pfsSuccess;
FResult.ErrorMessage := '';
try
FToken.ThrowIfCancelled; // already cancelled? skip the worker
FResult.Value := FWorker(FToken);
except
on E: EPdfOperationCancelled do
begin
FResult.Status := pfsCancelled;
FResult.ErrorMessage := E.Message;
end;
on E: Exception do
begin
FResult.Status := pfsFailure;
FResult.ErrorMessage := E.Message;
end;
end;
if Assigned(FReply) then
// Synchronize, not Queue: this thread is FreeOnTerminate, so a queued reply
// could be dropped by RemoveQueuedEvents before the main thread ran it.
Synchronize(DispatchReply);
end;
A a da a do de lição a geral da de sobrevive a a e da do à a do correção da específica. a e da de da a de a a Callbacks a assíncronos e a do e fire-and-forget e da do são a o a e do e a e padrão de a de do e a da e de do concorrência e a da de do mais a do fácil a de se errar sutilmente, porque o do a a da caminho do a de do feliz funciona na a a do primeira e do a a e da tentativa a de e do e da o a bug do a de da a a a a e da da a de de vive na da e a e da interação de da a da entre e do e a da e da a de ordem de a e da da da da desmontagem da da da da a thread da e a fila a da a. Ele não da se reproduz a do a sob do a e a da de e da e da e do do demanda a da e do. da do de Ele da de a depende a de a da e se da de e a do thread principal por um acaso da a a e drenou a e a a e a de a a fila a da e do da do de a a e de antes a a do da e que e e o e do de da worker terminasse da do e de e e a a a de do a e da a a a da se do e de do e de destruir da a do e a, do a da de de da da de da o do que da e de a é a um e do a tempo de a a da e que de do e o da agendador e do a a/scheduler da decide do a da de modo diferente e a do a de em de do a cada e da do da e do e execução da de a. do de Uma a e e da a primitiva da do e que a é correta do de da a uma de vez e da do, de a a da da na e binding da do e, da a a de de a de do de de vale muito mais de a do da do do a do da de que do do a o mesmo a e código derivado de novamente de a em a do da toda da aplicação e a da que do da e do do e precise do a da de uma de e renderização e de da do em a do da de e segundo da e a plano da do de a.
Por que os callbacks são ponteiros de método (method pointers)
O do worker e e a de resposta a de não da da a do e de a são métodos da e da do anônimos da e. a da a do Eles são a do da de a do a e tipos do da e de do e a de a e a da de da de do e a de a da de procedure of object, da e do a do de a e da da e do a de da a TPdfFutureWorker<T> do de e do da a de a e da de TPdfFutureReply<T>, e a essa e a a a de a escolha da do a de a a a e a é forçada a de da do a a pela da matriz de da do a do a e do do do a de da a de de da e compilador da de do do. O do PDFiumPas a de e a do compila a da no do e Delphi de a da a XE5 da a e do de a de e a versões de e e a da a e da posteriores da do e do e a e a e da no e do Free a Pascal 3.2 e a do da no a de a a e e do a e modo a da de e da e Delphi, do e da o a de da a de a FPC e de a 3.2 a nesse da a de e do modo da e e da e do a não do e da a da e suporta e da a do métodos do da anônimos a do da. e do Um do a e e da da da callback a e de de da da e a e da e e do de e a da a do e e de a de referência a da para do a a e a procedimento a da da do que e da da a e do e a a de a do de captura da e do da variáveis e de a do a a a a de da de da a e locais e da da e compilaria no Delphi e falharia no da FPC, a e a a então a unit a a do a do usa o e da da a menor denominador de e do da comum a do de da e que de ambos do a de e de a e a e os a da de a a e e de e compiladores de da aceitam da e a.
A do consequência a a da da do de e a da e da do a e a da prática a do e a do a é onde e a do do e o da estado e e e do de vive e a a a a da de do. e do de Um método da anônimo e a a a do da e a de do se de a do a a a a e fecha da sobre de da da e de do e de da os da e do e locais/locals a da e da do do de; do da um de ponteiro da a da do de método e a do e da não e de da. da a a e Então da da, a a do qualquer estado de e a a a a do que a do e a da do do a do e o da worker a do de de a e da e e de e de a a de da a precise, a do do e o índice e da a da página, do a o a a de a do zoom de do a de a, a a de a a o a de da de do do da do e e e a caminho e de a e a da a da a de do de da e da e de do de e de a e a saída, a e qualquer do da a e estado do e que da a a de da resposta a precise da e do a a a a de e de da atualizar de, e da e a do a e a da do o e controle da de imagem da da a do alvo ou e do da o a rótulo/label da de a e da da da de e do a progresso e do a, da a tem da de a do e do a a e de ficar do e da e do a de de a de de e da da da pendurado do do no a de do e da a da a da de do objeto de e cujo a de e do a a a a método e de de do e de está de do da de do a do a a e e sendo da e a passado e da. da a e do a Em do e um de visualizador de da a, da da do e da esse e a de e a a a de do de da a e objeto a e a e do do da geralmente e a da e a a de e do é da a o da form ou um controlador a a e a a a e a de e renderização da e de que do a e a a do ele a da a do da possui e da. da a de Isso da não de a da é uma a e solução do contorno e de de da e a de da da a de de a de imposta da de da de de de com a relutância a de a a; do isso do e da da de mantém a de da a de de da da a propriedade do de do a e e da da desse e e estado explícita do de a a e da da a de da a e e e da de visível de a de no a a e de do a objeto do e e da e do receptor de a e de da, em a a a do e de vez de da a do de a do e ficar da de da oculto e dentro da de uma e e closure e da do e.
Cancelamento cooperativo, não uma eliminação (kill) forçada
O e cancelamento aqui a da e da do de é cooperativo. da do Não a há de a do a de nenhuma API do a a de do de da que do a a e a e e a do da alcance e a thread de da do do a da worker da do e a de a a a finalize a a e da do, de porque a a a do a da finalizar de da uma thread no de da e meio do a da de da do de a do da de renderização deixa o da a PDFium da segurando locks e a e a de e bitmaps a da e do parcialmente a de e da da a do a e e escritos a, a e o de estado e do de a a e de do a processo após do e da uma a de eliminação/kill e a forçada da do e a de a e de não a é a do do da e a a do e algo e de e de do sobre a do de o qual a do a da e você possa da a raciocinar. Em e a da vez a de do e disso, e o a worker e e a recebe um token de de da da e e a da somente da leitura e da a a da e do da a de da do a espera-se que e da do a ele o de da da do verifique do, do a e o de a da de da da a de da loop a de da e e a a renderização é e e da da e a de do a escrito a de para verificá-lo de entre do da as da de páginas a ou a entre a a os a do do tiles e do, da a de onde a a a da de do parar da a de a da e a limpo.
O da token a oferece de da a três a da de e da e da de do de maneiras do e de da observar o da de do e cancelamento a e a da. a IsCancelled de do e da é da a do uma a verificação/poll da a e da a e a do do do e a da de e do booleana da do e da de e a da a e a barata da e do para a da a um a e loop do da de e do que da e da queira testar a da e do a da e a e do decidir da a a por e do da da de do si da a mesmo do a e e a a da a e do e a a. do ThrowIfCancelled a e do é do de da o e a caso a do a da do e da de a a e a comum a: a do da de e do e a e chame-o num e a do e a e da de ponto e da a natural a de e cancelamento a do de e, da se o da cancelamento a tiver a de e a de a a do do sido a do a de solicitado da de do, a do da da a a ele da de da do de do a levanta de a a do a o EPdfOperationCancelled a do, o a de a e do do a que a desenrola/unwinds e o de e a da a a worker da da a e da a de direto a do de a volta do a a a para o da a de do a a a e e da da a a da e de da future do. RegisterCallback e do a anexa do uma da de do notificação do de disparo do de da a único a a e do e de do a que da e a do a a e de do dispara da uma a do e vez da do quando do a do da e da do de e a da da a do a e da origem do e a do da a da for da de e da cancelada a a e e, útil do de quando de da um a de da a a worker da a a está de da a e a e da e da da a bloqueado de da de e em da do algo e de e que a ele a e possa e a de e a da e interromper da em da vez a de da ficar do de da a a do a de e sentado de em um loop a de da do apertado/tight a de.
A do da a a exceção da a de do de é e da a do de a de onde a fronteira do e de da e e thread importa de. a e a Quando o a de worker da da levanta de a do a o da a EPdfOperationCancelled, a do de o de da a do future do a da e de a a do a captura/catches de e o de a da e da do a e transforma a de e da e de de do a de em um a de status da do a de de cancelado e a a, de então da a da de a resposta do e a vê a da de a a do a da e a a IsCancelled da do a e da da de e da e da não do do da uma a a a da de e da a falha a e. O e da a a da do objeto e de da de a e exceção do em da do a si e de a da nunca de do a da é e a do marshaled a de a para da e a e da do a e a de da a a do da a thread de a e da principal e a da do a a. da a e Ele da a vive e morre a da de na a thread do do a de do de a da e da worker a do a do; do a da da a do e e de e da somente da a a a a da de do do e a da e de e a sua do e string do de da da a de de mensagem da é a da copiada da a de do para da e dentro a da da de da de do da de do a do do e de a do de a a e de do a ErrorMessage. a da Marshaling do um objeto da de da a da exceção vivo do do através e das threads da da significaria de da a alcançar de da da da da uma e da memória a a da de a do propriedade a de a do uma e de da thread da a que e de está do e a de terminando e a do, o a a que e de da a de é a a do da mesma de da do a e classe do a de a a de erro que a da de a do da de do a correção da do do a do Synchronize existe a para do a de a a prevenir e. a Um do a da a de do a a e código do do da de e status da do de de do e da de a uma string de da de e de e a e a e da cruzam a fronteira a de a do a do de e da maneira da a da e a a do e de limpa; do da a um do da de e objeto do de de não de do a a a.
Duas interfaces, para que um worker não possa cancelar a si mesmo
O da e e da cancelamento da e e de do é do dividido da de a e da de de através de do de e duas do a interfaces a e de de propósito. do A de IPdfCancellationTokenSource da do é do e do a do lado da de de da e de da do da do e e escrita da: da ele tem o de do da a da a Cancel, e de do a o do e dono da a a de que do e o do cria da a a de de, do de da do geralmente da a o a da do da de form da, e do a da e o a guarda e a e a do do de do e e a a chama a o a Cancel a a do da e quando a a do do usuário clica a de da do a do a de a no botão do a ou o form fecha. da A da da a do a e da IPdfCancellationToken a e e do a e da é o a da e da lado da do de a de leitura do a e: a a e da a ela e da da e a tem da a IsCancelled, a ThrowIfCancelled, a e a e a a RegisterCallback, de e de isso a do e a de a e de da do e da é tudo e a a a o que o da e da da worker da do sempre da e do a recebe de a a a e a a e do da a e a. a do a Um da de objeto da de a da do e da concreto implementa de a ambos do da, mas do e a a de a do de a da ao worker e da de a do e a de e a só da de do a da e do é da e a a de da do a a a e entregue a a da o a a a de do da token do a e a da de, de da a do então de a ele do de a a a do da da não da da a do e da a da a a do da de a a da do a a tem e da a e maneira e de de do e do a da e de do e cancelar da a operação da que do da a do de a ele a está a de a da do da de a da rodando/running a da. A a da e de da divisão/split do e da a é da do a um do do a de do da da a a a e guarda-corpo/guard e da rail da de nível e do de da a da de API do. do Um a de da da worker a de que pudesse do a da e a do a a alcançar do e da a da o e e a do Cancel de da através a de de a de da e a a seu a token de convidaria um a e pedaço confuso de do de a a e de do de e de a código do e de a a a da a e do da a e da cancelar do a a e e de a de da a a a e a e de a si a da mesmo, e o de a e a sistema e de do de da a a a a da tipos da a e do e da remove da a a possibilidade a.
Há a a e a um da a e do detalhe a e da e a de da correspondente a de para a o e da e a e a do do de do caso de do onde um do a a da de do chamador da quer e de a e a uma a a a da e do e a da a e a do de da e do da renderização, a de a mas da nunca do da pretende a cancelá-la do. a Em e vez a da do de e da a do e da e forçar a da do e da uma do da nova do da da origem do da e a por do chamada da do da a e, a e unit da do do e da e da e da e a e do expõe a do a a da o da PdfNoCancellationToken, de do um da do a a e de token e a do da de a da de singleton da a e a a do da que de da está permanentemente no e de da da de do estado do a de da e da a da a da de a do de não-cancelado da do de a a a e e. a A da a da de a a Run a a o e substitui do do quando o do da de a a do da e argumento da a do do e token de a e da do a e a da a do é a deixado a como de e a da nil. Esse do a da singleton da a e é e do e do a construído da a a de antecipadamente a do/eagerly e do de a a a durante da a da e a de a inicialização a a da de do e e e a da a da da a a da e a da unit a em vez e a a a de e a preguiçosamente e/lazily e a da e no da de primeiro uso do a, a a de a e de da o de do a da e e a e a e do a motivo do da de e a a a de a a a a de a da é a concorrência do da a de a e novamente a do a. de Se do e da várias a e da a da chamadas a e a de da e do do a Run a e da da e da em a da do a da de diferentes e threads da a de worker e a do da da alcançassem a e da de de todas da a da e a de e a a a a de e uma a do a a a vez a a da a e da por e da um e a da a do e de a da da e do singleton de e e do da da de da da criado preguiçosamente de a a e, elas da a de da poderiam de da de do a do correr do e da de da a de de da e a de na a a e de a da sua de e e do construção, e de do a da vazar um do a duplicado da do a a a, da a a de ou de da da a e do da a e a de e observar da de brevemente e uma instância e da do a da da a do a e da a do meio-inicializada e. a Construí-lo do e a do a de e da antes e que de a qualquer do da e a a a da worker da a a de e da da e e da a da de a e da possa do da do e rodar a a e e a remove da a de a a corrida a do a e da e do a a e por da de do a completo de.
Rodando uma renderização cancelável
Na a prática e do a a você a cria de uma de da do origem do, mantém a da e do da a do de a de a da a da de a no form a do e da, da e passa da do de a seu e da Token a de do a e para a da a da o a Run do de da a a a a da a a do ao do lado do da a da de e da e de um do da método a a worker a da e e a a da e um e da a método a de e a de de e resposta do e da, da a e a de e e da de do da liga/wire a de do o de da a do e de da a botão de do e da e Cancelar da do à e de da da de da origem de e da. O da de e worker a de do a do do da e verifica a de e de o a a token e da a e a a enquanto a de e e de do da e do ele da de e do renderiza da a do a do; do a da da resposta de da a a a e atualiza e da do a da e de a a UI da e a da e a assim da de e a que do e a da do a do a o da do resultado a do de e da de da a e a da a e está da de da e de da de e a da a da volta do. da e a a Como a da os da callbacks são da ponteiros da a de e método e a do, do o worker e a do da de resposta da do e da lêem a da de o a que de da a do a e de do de da e a de do a a e do e a e da da e a da precisarem dos e da de do e de campos da do e form e da do
procedure TMainForm.StartRender;
begin
FCancelSource := TPdfCancellationTokenSource.New; // field, lives on the form
TPdfFuture<Boolean>.Run(RenderWorker, RenderReply, FCancelSource.Token);
end;
procedure TMainForm.CancelButtonClick(Sender: TObject);
begin
if Assigned(FCancelSource) then
FCancelSource.Cancel; // worker observes this at its next cancel point
end;
// Runs on a background thread. Reads FPageRange / FOutputDir from the form.
function TMainForm.RenderWorker(const AToken: IPdfCancellationToken): Boolean;
var
PageIndex: Integer;
begin
for PageIndex := FFirstPage to FLastPage do
begin
AToken.ThrowIfCancelled; // clean stop between pages
RenderOnePage(PageIndex); // synchronous PDFium rasterisation
end;
Result := True;
end;
// Runs on the main thread. Safe to touch the VCL here.
procedure TMainForm.RenderReply(const AResult: TPdfFutureResult<Boolean>);
begin
if AResult.IsSuccess then
StatusLabel.Caption := 'Render complete'
else if AResult.IsCancelled then
StatusLabel.Caption := 'Cancelled'
else
StatusLabel.Caption := 'Failed: ' + AResult.ErrorMessage;
end;
A do a resposta do e da da a e lida de com a do da todos a da de os a e da do três resultados, a de a da a porque do da a a da a todos da do a a e de a a de a do de os a da e três a a de a do são a do do da de a da a a de a de a da de do alcançáveis da e. do Uma da a da de do a e e da a do da a da a de e renderização da do e a de e de da a da a da a a de da a da do de e a da a da concluída da de e da do e e a relata do e da da do e da de a a de sucesso, do da a da a a um do usuário da a do a de e que a de da e e do a da e da da e do a a a a da de do pressionou da de da e e a a o a de da e de da e Cancelar de do do a da e da a de da da vê e do da o a a a da da ramo/branch cancelado a do de, de a e de a da da um de da de e a arquivo a da e do do a que a não e a e da da do pôde de do e da de a da do e da ser de e a da da e de a a de da e a a da de da e a da de da e escrito, da a de de a ou e a a a de a da uma de e a a da página e de da a da que de e do de da da a a a a do a e de do de e de da e falhou ao se do da do efetuar parsing, do a da do e de do chega de da de como da do a a a uma falha e do com a do da de uma mensagem e do. a Nenhum a do desses do da da ramos/branches da e do a bloqueia do, da e nenhum de a de e deles do e da toca a do da a de a e de da do e a na da da thread do worker, da e do e a o de da a do bitmap a de a de da a ou o a de status a a do que da e a do de o a a e a a da worker da do produziu é lido apenas da de da e do a do e da de depois que o do a do a future da da a a da da a do a e da o e de a tiver a da da entregado a na a e a thread de que de do e da e a da a a da e do e é da e a e a do e de a da dona do a da UI do de da do a.
A do a mesma do e e a disciplina e do de da a threading e compensa de da a em a e e outros a a do de lugares a e a e e a a a de do em de do a um visualizador da de a e e. A do e a a de do maneira e da como e do e e do os bitmaps e a a do e de da renderizados são a e da da mantidos e a de da reutilizados a e a do a de através do e de da a a do das mudanças e de da de de zoom é e a do da a da da a de da coberta do da a em a a da a e nossa de a nota da do a de e sobre do o cache da a do a de a a de a da do da de e e do renderização de e a do desempenho da de zoom de a da a da e e do de a e a a e do da e, e a da do a e da de da da a questão da de e e da da a a mais ampla e de do de da da do da e a manter a a a e a da e do e a e da da fronteira do a da e a do a da a e PDFium e da segura sob a do da o do Delphi a da e a e e da da da está a da e do a de da em do da de reforçando/hardening de a a ABI do da do do a da PDFium a a a e e da a da a do VCL da a do a da a a e da de para da da a segurança e do de e a da da de a e a memória da. de e do da A da da e a a da de do infraestrutura do a async da a da e do de e da da a e de descrita da da aqui e da da a de da do a a a é distribuída da como a da de e da e do a a e a da a a parte do do de da Componente do do a e da PDFium de para e do o da do a da Delphi da de a a a e C++Builder a, da a ao a e e do de lado a e a do do de do das da de do da a a do da e APIs a da a a da e de de da da renderização de a do, de da texto da a a do e de e de formulário a de e cobertas a em outros e do de do da a de a e lugares a de a neste de do a blog a a da da