I'm using DinkToPDF dll to convert an XML to PDF.
I need to generate 2000 PDF's.
So I try to do put the PDF generation logic inside for loop. It generates first 2 or 3 PDF's and then in the next iteration crashes with a native Exception
This is my PDF generation class. Generate() method will be called 2000 times inside a forloop
public static class PDFEngine { public static void Generate(string html, string directory, string fileName) { var converter = new BasicConverter(new PdfTools()); converter.PhaseChanged += Converter_PhaseChanged; converter.ProgressChanged += Converter_ProgressChanged; converter.Finished += Converter_Finished; converter.Warning += Converter_Warning; converter.Error += Converter_Error; var doc = new HtmlToPdfDocument() { GlobalSettings = { ColorMode = ColorMode.Color, Orientation = Orientation.Portrait, PaperSize = PaperKind.A4, }, Objects = { new ObjectSettings() { PagesCount = true, HtmlContent = html, WebSettings = { DefaultEncoding = "utf-8" }, HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true }, FooterSettings = { FontSize = 9, Right = "Page [page] of [toPage]" } } } }; byte[] pdf = converter.Convert(doc); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } using (FileStream stream = new FileStream($"{directory}\\{fileName}", FileMode.Create)) { stream.Write(pdf, 0, pdf.Length); } } private static void Converter_Error(object sender, DinkToPdf.EventDefinitions.ErrorArgs e) { Console.WriteLine("[ERROR] {0}", e.Message); } private static void Converter_Warning(object sender, DinkToPdf.EventDefinitions.WarningArgs e) { Console.WriteLine("[WARN] {0}", e.Message); } private static void Converter_Finished(object sender, DinkToPdf.EventDefinitions.FinishedArgs e) { Console.WriteLine("Conversion {0} ", e.Success ? "successful" : "unsucessful"); } private static void Converter_ProgressChanged(object sender, DinkToPdf.EventDefinitions.ProgressChangedArgs e) { Console.WriteLine("Progress changed {0}", e.Description); } private static void Converter_PhaseChanged(object sender, DinkToPdf.EventDefinitions.PhaseChangedArgs e) { Console.WriteLine("Phase changed {0} - {1}", e.CurrentPhase, e.Description); } }
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
Since this is an Exception generating from an Unmanaged dll, I can't catch it.
I tried adding
GC.Collect();
GC.WaitForPendingFinalizers();
during every loop but it's not working. I'm fully aware that this error is fatal and not good to continue but I don't have a way to process 2000 files.
Is there any other way to either
After a lot of trial and error I was able to make it work with a different way.
My intention is to run in 2000 times. My issue was when I put it inside the loop, I'm getting native exceptions
To make it work for my need
I removed the loop and generate PDF only for a single file. This file name I receive in a commandline argument
Then I created another console app that got a 2000 iteration loop and it'll call the main app as a Process.Start();
I can pass the filename as arguments
This way I managed to make for any number of iterations for time being. Since each process got different PID now Memory issue is not there