Cancellation and streaming across packages
Every X-Ray package that does non-trivial work follows the same three rules, so code written against one carries over to the others.
- The token comes last. A public method that does real work has an overload that takes a
CancellationTokenas its last parameter. Where the token is the only extra argument it may default todefault. - Cancellation is an
OperationCanceledException. A cancelled call throws it and nothing else. It is never wrapped in a package exception, never turned into a warning or an error item, and never swallowed by a recovery option such asSuppressErrors. A token that is already cancelled throws before the work starts. - Large outputs go to a
Stream. Where a result can be large (a PDF, a PNG, an MSG, an HTML page), there is an overload that writes to a stream you provide, so the whole result need not exist as one array. Thebyte[]andstringforms are thin wrappers over the stream forms.
A call that completes with a token returns the same result it returns without one.
Where each package stands
| Package | Token overloads | Stream outputs | Page |
|---|---|---|---|
| X-Ray.Content | Extractor.Extract, ExtractAsync |
Not applicable: the result is a document model | Cancellation |
| X-Ray.Office | OfficeDocument.Open, Extract, Layout, PdfRenderer, RasterRenderer, SheetHtmlWriter, the markup writers |
PDF, raster pages and sheet HTML | Cancellation and limits |
| X-Ray.Psd | Load, LoadAsync, ExtractText, Render, RenderBands, the encoders |
PNG, JPEG, thumbnail, and bands | Streams, cancellation and large files |
| X-Ray.Email | Every load, save, convert, render and copy | MSG, EML, HTML preview, attachments | Streams, cancellation and limits |
| X-Ray.Ics | Every load, expand, render and save | Save, ToHtml, WriteTo |
Writing, limits and cancellation |
| X-Ray.PS | Every load and conversion | PDF, PNG and per-page images, EPS | Limits, recovery and cancellation |
| X-Ray.OneNote | Document.Load, Save, HtmlWriter, NotebookToc.Load |
PDF and HTML | Cancellation, errors and limits |
The pattern
using XRay.Ics;
using XRay.Office;
using XRay.Office.Core.Documents;
using XRay.Office.Rendering.Pdf;
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var token = timeout.Token;
try
{
// The token is the last argument everywhere.
var calendar = Calendar.LoadFile("team.ics", cancellationToken: token);
using IDocument document = OfficeDocument.Open("report.docx", token);
IPageSequence pages = ((IPaginatedDocument)document).Layout(null, token);
// The result goes to a stream, here a file, instead of one array.
using var pdf = File.Create("report.pdf");
new PdfRenderer().Render(document, pages, pdf, token);
}
catch (OperationCanceledException)
{
// The same catch for every package. A partial output stream is not a valid file: discard it.
Console.WriteLine("cancelled or timed out");
}
Two details differ:
- A distinct timeout type. X-Ray.Office's
LayoutOptions.TimeoutthrowsLayoutTimeoutException, a subtype ofOperationCanceledException, so a caller can tell a document that took too long from a caller that cancelled. - Partial output. A cancelled stream write leaves what it had written in the stream. X-Ray.OneNote deletes a file it was saving to by path when the save fails or is cancelled; with a stream it cannot, so discard the stream.
What cannot be interrupted
A token is polled by the library's own loops. One call into a library that has no token runs to its
end. Each package page says which calls these are. For X-Ray.Content they are a single
System.Text.Json parse of one large document, SkiaSharp decoding one image, X-Ray.Psd's Load
and ExtractText, and PDFium rasterising one page. For X-Ray.PS they are the Type 1 font resource
patterns, the XML parser for one part and the CLR's own zlib.
Limits beside cancellation
A token covers a caller that loses patience. Limits cover a file that is hostile on arrival, and they work without a token: parse limits in X-Ray.Ics, interpreter limits in X-Ray.PS, layout limits in X-Ray.Office, bomb and recursion ceilings in X-Ray.Content, and the structural budgets in X-Ray.OneNote. Use both when you convert files you do not control.