C# CancellationToken con Iron Suite: Pipeline SII/VeriFactu/AEAT y LOPDGDD en España
Los desarrolladores modernos de .NET a menudo trabajan con programación asincrónica al integrar bibliotecas como IronPDF, IronOCR, IronWord y IronXL. Estos productos ejecutan frecuentemente tareas de larga duración, tales como el renderizado de PDFs, el procesamiento de contenido OCR o la generación de grandes hojas de cálculo, y la forma correcta de mantener las aplicaciones receptivas es usar la cancelación basada en C# CancellationToken.
Este artículo explica cómo utilizar tokens de cancelación, cómo un método acepta un token, cómo gestionar la cancelación de tareas y cómo integrar estos patrones con las bibliotecas de Iron Software de forma adecuada y oportuna. También cubrimos las mejores prácticas, la gestión de recursos y cómo utilizar varios CancellationTokens simultáneamente.
Por qué son importantes las solicitudes de cancelación en las cargas de trabajo de Iron Software

Las herramientas de Iron Software suelen ejecutar operaciones asíncronas, por ejemplo:
- Una conversión de HTML a PDF de IronPDF HTML-to-PDF conversion
- Una extracción OCR de larga duración de IronOCR OCR extraction
- Una construcción de documento de IronWord o IronXL dentro de los Servicios en Segundo Plano
- Una gran solicitud web HttpClient antes de la generación del PDF
Estas pueden ser operaciones de larga duración que deben terminar de forma adecuada cuando un usuario hace clic en un botón de Cancelar, navega fuera, o cuando el código que llama emite una CancellationRequest.
El uso de tokens de cancelación garantiza:
- Aplicaciones con capacidad de respuesta
- Mejor gestión de recursos
- Liberación controlada de recursos no gestionados
- Un modelo limpio de cancelación cooperativa
Entendiendo los conceptos básicos de CancellationToken de C
C# proporciona la clase CancellationTokenSource, que crea un token CancellationToken. Un CTS new CancellationTokenSource() puede crear un token que se pasa a métodos asíncronos.
var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;Dim cts As New CancellationTokenSource()
Dim token As CancellationToken = cts.TokenUn token se transmite mediante un parámetro de método:
public async Task ProcessPdfAsync(string html, CancellationToken token)public async Task ProcessPdfAsync(string html, CancellationToken token)Public Async Function ProcessPdfAsync(html As String, token As CancellationToken) As TaskDentro del método, se comprueba periódicamente:
token.ThrowIfCancellationRequested();token.ThrowIfCancellationRequested();token.ThrowIfCancellationRequested()o inspeccionar la propiedad IsCancellationRequested:
if (token.IsCancellationRequested)
{
Console.WriteLine("Cancellation requested.");
return;
}if (token.IsCancellationRequested)
{
Console.WriteLine("Cancellation requested.");
return;
}If token.IsCancellationRequested Then
Console.WriteLine("Cancellation requested.")
Return
End IfEsto proporciona un patrón de cancelación cooperativa donde el evento de operación cancelada ocurre solo cuando su código revisa el token.
Uso de CancellationToken con IronPDF
El renderizado HTML de IronPDF está diseñado para programación asincrónica, por lo que puede integrar la cancelación de manera natural.
public async Task<PdfDocument> BuildPdfAsync(string html, CancellationToken token)
{
Console.WriteLine("\n[Generator] Starting PDF rendering process...");
var renderer = new ChromePdfRenderer();
token.ThrowIfCancellationRequested();
Console.WriteLine("[Generator] Simulating a 2-second delay...");
await Task.Delay(2000, token);
token.ThrowIfCancellationRequested();
Console.WriteLine("[Generator] Delay complete. Starting actual rendering...");
// This is the working overload for your library version
return await renderer.RenderHtmlAsPdfAsync(html);
}public async Task<PdfDocument> BuildPdfAsync(string html, CancellationToken token)
{
Console.WriteLine("\n[Generator] Starting PDF rendering process...");
var renderer = new ChromePdfRenderer();
token.ThrowIfCancellationRequested();
Console.WriteLine("[Generator] Simulating a 2-second delay...");
await Task.Delay(2000, token);
token.ThrowIfCancellationRequested();
Console.WriteLine("[Generator] Delay complete. Starting actual rendering...");
// This is the working overload for your library version
return await renderer.RenderHtmlAsPdfAsync(html);
}Imports System
Imports System.Threading
Imports System.Threading.Tasks
Public Class PdfGenerator
Public Async Function BuildPdfAsync(html As String, token As CancellationToken) As Task(Of PdfDocument)
Console.WriteLine(vbCrLf & "[Generator] Starting PDF rendering process...")
Dim renderer As New ChromePdfRenderer()
token.ThrowIfCancellationRequested()
Console.WriteLine("[Generator] Simulating a 2-second delay...")
Await Task.Delay(2000, token)
token.ThrowIfCancellationRequested()
Console.WriteLine("[Generator] Delay complete. Starting actual rendering...")
' This is the working overload for your library version
Return Await renderer.RenderHtmlAsPdfAsync(html)
End Function
End ClassEjemplo de salida de la consola

Aquí se muestra una tarea pública asíncrona que admite la cancelación en varios puntos. Cuando se produce una cancelación, el método lanza una excepción OperationCanceledException, que se maneja en un bloque catch.
Uso de CancellationToken con IronOCR
La operación de larga duración de IronOCR de escaneo de imágenes también se beneficia de un CancellationToken interno:
public class OcrProcessor
{
private readonly IronOcr.IronTesseract ocr = new IronOcr.IronTesseract();
public async Task<string> ExtractTextAsync(string path, CancellationToken token)
{
// Check for cancellation immediately upon entering the method.
token.ThrowIfCancellationRequested();
// Run the synchronous OCR method on a background thread.
// This is the correct pattern for cancellable synchronous wrappers.
return await Task.Run(() => ocr.Read(path).Text, token);
}
}public class OcrProcessor
{
private readonly IronOcr.IronTesseract ocr = new IronOcr.IronTesseract();
public async Task<string> ExtractTextAsync(string path, CancellationToken token)
{
// Check for cancellation immediately upon entering the method.
token.ThrowIfCancellationRequested();
// Run the synchronous OCR method on a background thread.
// This is the correct pattern for cancellable synchronous wrappers.
return await Task.Run(() => ocr.Read(path).Text, token);
}
}Imports System.Threading
Imports System.Threading.Tasks
Imports IronOcr
Public Class OcrProcessor
Private ReadOnly ocr As New IronTesseract()
Public Async Function ExtractTextAsync(path As String, token As CancellationToken) As Task(Of String)
' Check for cancellation immediately upon entering the method.
token.ThrowIfCancellationRequested()
' Run the synchronous OCR method on a background thread.
' This is the correct pattern for cancellable synchronous wrappers.
Return Await Task.Run(Function() ocr.Read(path).Text, token)
End Function
End ClassEjemplo de resultado

La generación de documentos IronWord y el montaje de hojas de cálculo IronXL funcionan de la misma manera. Dado que se trata de operaciones cancelables, el patrón de cancelación cooperativa evita el bloqueo de hilos de la interfaz de usuario o de servicios en segundo plano.
Comprobación periódica de cancelación en operaciones largas
Un patrón común es hacer bucles y comprobar la cancelación:
public async Task LongRunningOperation(CancellationToken token)
{
for (int i = 0; i < 1000; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(10, token); // await Task.Delay helps cooperative cancellation
}
}public async Task LongRunningOperation(CancellationToken token)
{
for (int i = 0; i < 1000; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(10, token); // await Task.Delay helps cooperative cancellation
}
}Imports System.Threading
Imports System.Threading.Tasks
Public Async Function LongRunningOperation(token As CancellationToken) As Task
For i As Integer = 0 To 999
token.ThrowIfCancellationRequested()
Await Task.Delay(10, token) ' Await Task.Delay helps cooperative cancellation
Next
End FunctionEsto garantiza que las solicitudes de cancelación se gestionen de forma adecuada y oportuna, y que el sistema no desperdicie ciclos.
Uso de CancellationToken con HttpClient antes de la renderización de IronPDF
Al realizar una solicitud web para obtener HTML antes de generar un PDF, pase siempre el token:
var client = new HttpClient();
public async Task<string> FetchHtmlAsync(string url, CancellationToken token)
{
var response = await client.GetAsync(url, token);
if (!response.IsSuccessStatusCode)
throw new Exception("Error occurred while requesting content.");
return await response.Content.ReadAsStringAsync(token);
}var client = new HttpClient();
public async Task<string> FetchHtmlAsync(string url, CancellationToken token)
{
var response = await client.GetAsync(url, token);
if (!response.IsSuccessStatusCode)
throw new Exception("Error occurred while requesting content.");
return await response.Content.ReadAsStringAsync(token);
}Imports System.Net.Http
Imports System.Threading
Imports System.Threading.Tasks
Dim client As New HttpClient()
Public Async Function FetchHtmlAsync(url As String, token As CancellationToken) As Task(Of String)
Dim response = Await client.GetAsync(url, token)
If Not response.IsSuccessStatusCode Then
Throw New Exception("Error occurred while requesting content.")
End If
Return Await response.Content.ReadAsStringAsync(token)
End FunctionEsto garantiza que si el usuario se aleja, el HttpClient se cancele en el momento oportuno.
Cancelación en .NET Core Servicios de fondo
los servicios de fondo de .NET Core incluyen un CancellationToken interno que se pasa automáticamente al método ExecuteAsync. Utilícela cuando ejecute herramientas de Iron Software:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await ProcessPdfAsync("<h1>Hello</h1>", stoppingToken);
await Task.Delay(5000, stoppingToken);
}
}protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await ProcessPdfAsync("<h1>Hello</h1>", stoppingToken);
await Task.Delay(5000, stoppingToken);
}
}Protected Overrides Async Function ExecuteAsync(stoppingToken As CancellationToken) As Task
While Not stoppingToken.IsCancellationRequested
Await ProcessPdfAsync("<h1>Hello</h1>", stoppingToken)
Await Task.Delay(5000, stoppingToken)
End While
End FunctionEste es el patrón general para las tareas de larga duración del lado del servidor.
Bestes prácticas para el uso de tokens de cancelación con Iron Software
Pase siempre CancellationToken a los métodos asíncronos.
Utilice ThrowIfCancellationRequested dentro de bucles.
Preferir await Task.Delay en lugar de bucles cerrados.
Combine tokens con LinkedTokenSource.
Maneje siempre OperationCanceledException.
Utilice la cancelación para una mejor gestión de recursos y aplicaciones con capacidad de respuesta.
- Recuerde que C# es un lenguaje de programación orientado a objetos, así que diseñe su método de cancelación y su lógica de cancelación de forma limpia.
Consideraciones avanzadas para la cancelación de tareas
Para asegurarnos de que este es un buen artículo para cualquier desarrollador .NET, aquí hay una breve sección complementaria que incorpora la terminología relevante restante a la vez que refuerza las mejores prácticas.
La cancelación de tareas en C# no es automática; depende de la lógica de cancelación implementada dentro de su método. La propiedad token debe comprobarse, y el token devuelto a los consumidores debe permitirles determinar si la operación se ha cancelado o completado con éxito. Si no se puede finalizar una solicitud, el sistema debe terminar de manera adecuada y oportuna.
Si una interfaz de usuario activa un botón de cancelación, el método cancel de su CancellationTokenSource señalará la cancelación, y su código deberá comprobar periódicamente a través de token.IsCancellationRequested. Cuando ocurren eventos de operación cancelada, usted libera recursos y devuelve el control al que llama.
Una operación de larga duración como el escaneo de IronOCR de documentos profundamente anidados o la generación de IronXL de hojas de cálculo masivas debe pasar el CancellationToken a través de cada capa. Cuando el usuario sale de la página, la operación debe terminar limpiamente.
Los productos de Iron Software facilitan esta tarea porque siguen de forma nativa el modelo de programación asíncrona de .NET. Cuando escriba sus propias bibliotecas, considere la posibilidad de seguir las mismas prácticas recomendadas para que sus consumidores puedan cancelar las operaciones en el momento oportuno sin fugas de memoria ni retención de recursos no gestionados.
CancellationToken en pipelines regulados españoles
En el contexto español, el patrón CancellationToken es especialmente relevante para las operaciones de larga duración relacionadas con la fiscalidad electrónica:
Envíos al SII de la AEAT: El Suministro Inmediato de Información (SII) requiere enviar los datos de facturas a los servicios web de la Agencia Estatal de Administración Tributaria (AEAT) en tiempo real. Si la conexión se interrumpe o el usuario cancela la operación, un CancellationToken propagado correctamente garantiza que IronPDF termine la generación del PDF limpiamente, que la solicitud HTTP a la AEAT se cancele sin dejar recursos bloqueados, y que la transacción no quede en estado inconsistente bajo la LOPDGDD (los datos de NIF/DNI/NIE del cliente deben estar bajo control transaccional en todo momento).
Generación de Facturae en batch: Las empresas con volúmenes altos de Facturae o VeriFactu suelen procesar facturas en lote durante las noches. Un CancellationToken integrado en el pipeline IronPDF permite que el operador detenga el procesamiento limpiamente si se detecta un error de validación FNMT/eIDAS, sin dejar archivos PDF parciales en el sistema de archivo fiscal.
Procesamiento OCR de documentos fiscales: IronOCR extrae texto de contratos y facturas bajo la LOPDGDD y el Esquema Nacional de Seguridad (ENS). Los procesos OCR de larga duración (documentos de cientos de páginas con datos DNI/NIE de empleados) pueden cancelarse controladamente cuando el usuario sale o el sistema detecta un timeout del Banco de España o la CNMV, liberando la memoria con los datos personales antes de que puedan ser accedidos por otros procesos.
// Pipeline VeriFactu + AEAT con CancellationToken
// Cumple LOPDGDD: datos NIF/DNI liberados al cancelar
public async Task<string> EnviarFacturaAsync(
FacturaeData factura,
CancellationToken cancellationToken)
{
// Generar PDF representativo — cancelable
cancellationToken.ThrowIfCancellationRequested();
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(
await plantillaService.RenderizarAsync(factura, cancellationToken),
cancellationToken);
// Enviar al endpoint SII/VeriFactu de la AEAT — cancelable
return await aeatService.EnviarVeriFactuAsync(
factura, pdf.BinaryData, cancellationToken);
}// Pipeline VeriFactu + AEAT con CancellationToken
// Cumple LOPDGDD: datos NIF/DNI liberados al cancelar
public async Task<string> EnviarFacturaAsync(
FacturaeData factura,
CancellationToken cancellationToken)
{
// Generar PDF representativo — cancelable
cancellationToken.ThrowIfCancellationRequested();
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(
await plantillaService.RenderizarAsync(factura, cancellationToken),
cancellationToken);
// Enviar al endpoint SII/VeriFactu de la AEAT — cancelable
return await aeatService.EnviarVeriFactuAsync(
factura, pdf.BinaryData, cancellationToken);
}Imports System.Threading
Imports System.Threading.Tasks
' Pipeline VeriFactu + AEAT con CancellationToken
' Cumple LOPDGDD: datos NIF/DNI liberados al cancelar
Public Class FacturaService
Public Async Function EnviarFacturaAsync(
factura As FacturaeData,
cancellationToken As CancellationToken) As Task(Of String)
' Generar PDF representativo — cancelable
cancellationToken.ThrowIfCancellationRequested()
Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(
Await plantillaService.RenderizarAsync(factura, cancellationToken),
cancellationToken)
' Enviar al endpoint SII/VeriFactu de la AEAT — cancelable
Return Await aeatService.EnviarVeriFactuAsync(
factura, pdf.BinaryData, cancellationToken)
End Function
End ClassConclusión
Usar C# CancellationToken con IronPDF, IronOCR, IronWord y IronXL proporciona un enfoque de cancelación cooperativa que mantiene las aplicaciones receptivas, eficientes y robustas. Al aplicar las mejores prácticas en programación asincrónica, pasar tokens a tareas asincrónicas y verificar periódicamente la cancelación, puede construir aplicaciones .NET más rápidas, seguras y mantenibles que terminen de manera adecuada cuando sea necesario.
