【问题标题】:LocalReport rendering causing OutOfMemory exceptionsLocalReport 渲染导致 OutOfMemory 异常
【发布时间】:2015-10-27 18:54:53
【问题描述】:

我有一个 WindowsService,它通过 LocalReports(RDLC 报告)将 XML 文件转换为 PDF。它工作得很好而且速度很快,但我正在努力解决类似于here 的内存泄漏问题。

看来.Render("PDF") 方法是出现问题的地方。 VS2015 中的分析会话显示了ServerIdentity 使用的大量内存。如果我注释掉 .Render("PDF"),这不会出现。

规格

  • 应用程序是 .NET 4.5
  • 应用程序使用 VS2012 中的 ReportViewer 库(我也尝试过 2015 年,并且行为相同)
  • 专为“任何 CPU”构建,可能以 x86 运行
  • 报告并不大,但我们会运行很多,所以几周后内存就会用完(一页报告,一天可能十几页或更多)。

代码

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);
        }
    }

其他说明

  • 如果我从不调用.Render("PDF"),内存永远不会超过20MB 左右。
  • 同样,如果我从不渲染,堆中就没有ServerIdentity 或 Microsoft.ReportingServices.OnDemanProcessing.*` 对象。这是消耗 90% 以上内存的地方,但我无法 GC 那些内存。

【问题讨论】:

  • 您是否愿意考虑使用创可贴而不是修复?例如,如果您在进程外执行此工作,则每次外部进程结束时都会自动恢复内存。
  • 这是个好主意。该服务曾经是 Windows 中的计划任务,但在编写时很难支持。这就是为什么没有发生这些内存问题的原因。是否需要在单独的应用程序中进行处理,还是有办法从这里的代码中分离出一个进程?
  • 出于隔离的目的,我(个人)会制作一个单独的 exe,或者可能是一个 Web 服务(localhost 或其他)。
  • 是的,我最终使用了这个示例代码:alandjackson.wordpress.com/2013/05/29/c-out-of-process-workers 它确实工作得更好,但我已经向 MS 提交了 Premier 支持票,看看他们是否可以提供更细致入微的答案至于为什么会发生这种行为。如果我发现,我会发布作为答案。如果没有,我会发布我的解决方案。

标签: c# pdf out-of-memory rdlc reportviewer


【解决方案1】:

将你应用的编译目标改为x64并调用

report.ReleaseSandboxAppDomain();

渲染方法之后。记得 Dispose 报表对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2018-09-03
    • 2020-06-15
    • 1970-01-01
    • 2011-09-03
    相关资源
    最近更新 更多