When calling a PDF export in a high-concurrency environment the internal state can get corrupted because it uses a non-thread safe collection internally.
Sample code:
void WriteToPdf(RadFlowDocument document, Stream outputStream) {
PdfFormatProvider pdfWriter = new() {};
pdfWriter.Export(document, outputStream);
}When calling it like this:
Parallel.ForEachAsync(listOfDocuments, (document, _) => {
WriteToPdf(document, Stream.Null);
});An exception may occur:
System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
at System.Collections.Generic.Dictionary`2.FindValue(TKey key)
at Telerik.Windows.Documents.Fixed.Model.Fonts.FontsRepository.TryCreateFont(FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontBase& font)
at Telerik.Windows.Documents.Flow.FormatProviders.Pdf.Utils.Extensions.CopyPropertiesFrom(CharacterProperties fixedProperties, PdfExportContext context, CharacterProperties properties)
at Telerik.Windows.Documents.Flow.FormatProviders.Pdf.Export.PdfExporter.CreateListLevel(ListLevel flowLevel)
at Telerik.Windows.Documents.Flow.FormatProviders.Pdf.Export.PdfExporter.CreateList(List flowList)
at Telerik.Windows.Documents.Flow.FormatProviders.Pdf.Export.PdfExporter.ExportDocument(RadFlowDocument document, RadFixedDocumentEditor editor)
at Telerik.Windows.Documents.Flow.FormatProviders.Pdf.Export.PdfExporter.ExportInternal()
at Telerik.Windows.Documents.Common.FormatProviders.FormatProviderBase`1.Export(T document, Stream output)
at xxxxx.Application.Common.PdfGeneration.PdfWriter.WriteToPdf(RadFlowDocument document, Stream outputStream) The state is then corrupted forever, until the application is restarted.
Realistic scenario where this is also reproduced: Web application that generates PDFs and is called concurrently.
InvalidOperationException Cannot find the "endstream" keyword with a specific file.
According to the PDF Specification:
A stream consists of a dictionary followed by zero or more bytes bracketed between the keywords stream and endstream:
dictionary
stream
… Zero or more bytes …
endstream
InvalidCastException is thrown when a name start character is followed by a literal string start character.
System.InvalidCastException: Unable to cast object of type 'Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.Model.Types.PdfInt' to type 'Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.Model.Types.PdfName'.
When inserting ligature languages text into a block, the text doesn't appear on the generated PDF file.
With the following sample code, the issue can be reproduced:
private static string fileName = "Hello.pdf";
static void Main(string[] args)
{
byte[] fontData = File.ReadAllBytes("calibri.ttf");
FontFamily fontFamily = new FontFamily("Calibri");
FontsRepository.RegisterFont(fontFamily, FontStyles.Normal, FontWeights.Normal, fontData);
RadFixedDocument document = new RadFixedDocument();
RadFixedPage page = new RadFixedPage();
string text = "مرحبا";
var reversedText = text.ToCharArray();
Array.Reverse(reversedText);
Block block = new Block();
block.InsertText(new FontFamily("Calibri"), new string(reversedText));
FixedContentEditor editor = new FixedContentEditor(page);
editor.DrawBlock(block);
document.Pages.Add(page);
PdfFormatProvider provider = new PdfFormatProvider();
using (Stream output = File.OpenWrite(fileName))
{
provider.Export(document, output);
}
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = fileName;
Process.Start(fileName);
}
Some documents loaded through WordsProcessing and then exported to a RadFixedDocument by utilizing the ExportToFixedDocument() method, fails on export through ImageFormatProvider with System.AggregateException.
As a workaround, you can export the RadFixedDocument to a PDF and then import it again before exporting it to an image.
var pdfFixedProvider = new Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider();
bytes = pdfFixedProvider.Export(fixedDocument);
fixedDocument = pdfFixedProvider.Import(bytes);
When loading a PDF generated with PdfProcessing in PDF Accessibility Checker 2021 (PAC) an exception is thrown: "Object reference not set to an instance of an object".
It is reproducible with all PdfComplianceLevel export options.