I am running into a memory issue when trying to perform a mail merge. I need to do two things:
1. Generate individual PDF files to be stored on a file share
2. generate a single PDF so it could be sent to a printer as a single job.
I am noticing, that after my large PDF file is generated, the memory usage remains very large. When I re-run the process, it starts climbing up, but then falls back down to an acceptable level during the generation of single document, only to climb back up during the final single PDF. I am pasting my code below. For some odd reason my random data isn't actually making it into the files, but since that's not my problem at this moment, I am not concerned about it.
using System;using System.Collections.Generic;using System.Data;using System.IO;using System.Linq;using System.Threading.Tasks;using Telerik.WinForms.Documents.FormatProviders.OpenXml.Docx;using Telerik.WinForms.Documents.FormatProviders.Pdf;using Telerik.WinForms.Documents.Model;namespace MailMergeMemoryBenchmark{ public partial class RadForm1 : Telerik.WinControls.UI.RadForm { List<DummyItem> dataSource; public RadForm1() { //get the rest of the string at http://pastebin.com/i6PZiJ1c
byte[] template = Convert.FromBase64String(@"UEsDBBQ...[TRUNCATED]"); dataSource = new List<DummyItem>(); for (int i = 0; i < 1000; i++) { dataSource.Add(DummyItem.GetRandom()); } InitializeComponent(); var provider = new DocxFormatProvider(); radRichTextEditor1.Document = provider.Import(template); radRichTextEditor1.ScaleFactor = new Telerik.WinForms.Documents.Model.SizeF(.4f, .4f); radRichTextEditor1.ChangeAllFieldsDisplayMode(FieldDisplayMode.Code); radRichTextEditor1.Document.ShowMergeFieldsHighlight = true; radRichTextEditor1.Document.MailMergeDataSource.ItemsSource = dataSource; } private async void btnPerformMailMerge_Click(object sender, EventArgs e) { btnPerformMailMerge.Enabled = false; var progress = new Progress<string>(value => UpdateProgress(value)); await Go(progress); btnPerformMailMerge.Enabled = true; } private void UpdateProgress(string value) { radLabel1.Text = value + Environment.NewLine; } private Task<bool> Go(IProgress<string> progress) { return Task.Run(() => { var pdfProvider = new PdfFormatProvider(); PdfExportSettings pdfExportSettings = new PdfExportSettings() { ContentsCompressionMode = PdfContentsCompressionMode.Automatic, ContentsDeflaterCompressionLevel = 9, FloatingUIContainersExportMode = PdfInlineUIContainersExportMode.Image, ImagesCompressionMode = PdfImagesCompressionMode.Automatic, ImagesDeflaterCompressionLevel = 9, InlineUIContainersExportMode = PdfInlineUIContainersExportMode.Image, }; pdfProvider.ExportSettings = pdfExportSettings; byte[] letterBytes; radRichTextEditor1.Document.MailMergeDataSource.MoveToFirst(); int i = 0; do { using (var document = radRichTextEditor1.Document.MailMergeCurrentRecord()) { letterBytes = pdfProvider.Export(document); File.WriteAllBytes($"{i}-{DateTime.Now.Ticks}.pdf", letterBytes); } letterBytes = null; progress.Report($"Merged {i + 1} out of {dataSource.Count()}"); i++; } while (radRichTextEditor1.Document.MailMergeDataSource.MoveToNext()); progress.Report($"Starting large PDF creation"); using (var document = radRichTextEditor1.MailMerge(true)) { letterBytes = pdfProvider.Export(document); File.WriteAllBytes($"ALL RECORDS-{DateTime.Now.Ticks}.pdf", letterBytes); } progress.Report($"Done with large PDF creation"); letterBytes = null; pdfProvider = null; pdfExportSettings = null; GC.Collect(); return true; }); } } internal class DummyItem { public string ContactName; public string CompanyName; public string Address; public static DummyItem GetRandom() { return new DummyItem() { ContactName = RandomStringGenerator.RandomString(20, 40), CompanyName = RandomStringGenerator.RandomString(20, 40), Address = RandomStringGenerator.RandomString(100, 200) }; } } internal static class RandomStringGenerator { private const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 "; private static Random random = new Random(); public static string RandomString(int minLength, int maxLength) { var length = random.Next(minLength, maxLength); return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); } }}