1

I have a WindowsService that converts XML files to a PDF via LocalReports (RDLC reports). It works very well and is fast, but I'm struggling with memory leak problems similar to those here.

It appears the .Render("PDF") method is where the problems are appearing. A profiling session in VS2015 shows a huge about of memory used by ServerIdentity. This doesn't appear if I comment out .Render("PDF").

Specs

  • Application is .NET 4.5
  • Application uses ReportViewer library from VS2012 (I've tried 2015, too, and same behavior)
  • Built for 'Any CPU', runs as x86 presumably
  • Reports aren't huge, but we run quite a few so after a few weeks memory gets used up (1 page reports, maybe a dozen or more a day).

Code

public static byte[] GenerateReport(string name, IEnumerable<ReportDataSource> dataSources)
    {
        try
        {
            byte[] pdfBytes; 
            using (Stream reportStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
            {
                LocalReport localReport = new LocalReport();
                localReport.LoadReportDefinition(reportStream);

                foreach (var dataSource in dataSources)
                {
                    localReport.DataSources.Add(dataSource);
                }

                pdfBytes = localReport.Render("PDF");

                //Cleanup!
                localReport.DataSources.Clear();
                localReport.ReleaseSandboxAppDomain();
                localReport.Dispose();
            }

            return pdfBytes;
        }
        catch (Exception ex)
        {
            throw new Exception("Error generating report at " + name, ex);
        }
    }

Other notes

  • If I never call .Render("PDF"), the memory never grows beyond 20MB or so.
  • Similarly, if i never render, there's no ServerIdentity or Microsoft.ReportingServices.OnDemanProcessing.*` objects in the heap. This is where 90%+ of the memory is consumed but I have no way to GC that memory.
Community
  • 1
  • 1
Killnine
  • 5,728
  • 8
  • 39
  • 66
  • Would you be willing to consider a bandaid instead of a fix? For instance, if you did this work out-of-process, then the memory would be automatically recovered each time your external process ended. – tgolisch Oct 27 '15 at 21:23
  • That's a good thought. This service used to be a Scheduled Task in Windows but support was very difficult for that in the way it was written. That's why these memory issues didn't occur. Would it require the processing to be in a separate application or is there a way to spin off a process from within code here? – Killnine Oct 28 '15 at 12:30
  • For purposes of isolation, I (personally) would either make a separate exe, or maybe a web service (localhost or otherwise). – tgolisch Oct 28 '15 at 18:27
  • yep, I ended up using this sample code: https://alandjackson.wordpress.com/2013/05/29/c-out-of-process-workers/ It definitely works much better, but I've put in a Premier support ticket in with MS to see if they can provide a more nuanced answer as to why this behavior is occurring. If I find out, Ill post as answer. If not, I'll post my solution instead. – Killnine Oct 28 '15 at 19:39

1 Answers1

0

Change the compilation target of your application to x64 and call

report.ReleaseSandboxAppDomain();

After Render method. Remember to Dispose the report object.

Bruno Leitão
  • 764
  • 10
  • 16