C# RDLC内存泄漏

C# RDLC内存泄漏,c#,.net,rdlc,C#,.net,Rdlc,在我的应用程序(.NETFramework 4.5)中,我呈现了一些RDLC报告(50-60),以便将它们导出为单个PDF 不幸的是,似乎有一个很大的内存泄漏,基本上每个LocalReport都不会得到处理 这是我的代码: public void ProcessReport(ReportDataSource[] reportDS, string reportPath) { const string format = "PDF"; string deviceInfo = null;

在我的应用程序(.NETFramework 4.5)中,我呈现了一些RDLC报告(50-60),以便将它们导出为单个PDF

不幸的是,似乎有一个很大的内存泄漏,基本上每个
LocalReport
都不会得到处理

这是我的代码:

public void ProcessReport(ReportDataSource[] reportDS, string reportPath)
{
    const string format = "PDF";
    string deviceInfo = null;
    string encoding = String.Empty;
    string mimeType = String.Empty;
    string extension = String.Empty;
    Warning[] warnings = null;
    string[] streamIDs = null;
    Byte[] pdfArray = null;

    using (var report = new LocalReport())
    {
        report.EnableExternalImages = true;
        report.ReportEmbeddedResource = reportPath;
        report.Refresh();

        foreach (var rds in reportDS)
        {
            report.DataSources.Add(rds);
        }
        report.Refresh();

        try
        {
            pdfArray = report.Render(format, deviceInfo, out mimeType, out encoding,
                out extension, out streamIDs, out warnings);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.InnerException.Message);
            throw;
        }

        report.ReleaseSandboxAppDomain();
        report.Dispose();

        //Add pdfArray to MemoryStream and then to PDF - Doesn't leak
    }
}
我通过查看Visual Studio内存面板发现内存泄漏,每次
report.Render
get称之为add 20-30mb,在我关闭应用程序之前,内存不会下降。我确信使用
MemoryStream
不是问题所在,因为即使有注释,我的内存仍然有200mb-250mb,而且永远不会被释放。这是不好的,因为在运行这个应用程序3-4次之后,它会达到>1GB,直到不再运行为止。我还试图手动调用
垃圾收集器
,但没有成功。应用程序是32位的


我能做些什么来解决这个问题?

我有一个真正的解决方案,可以解释为什么

事实证明,LocalReport在这里使用.NETRemoting动态创建一个子appdomain并运行该报告,以避免在某个地方发生内部泄漏。然后我们注意到,最终,报告将在10到20分钟后释放所有内存。对于生成大量PDF的人来说,这是行不通的。然而,这里的关键是他们正在使用.NET远程处理。远程处理的关键部分之一是所谓的“租赁”。租赁意味着它将把封送对象保留一段时间,因为远程处理的设置成本通常很高,而且可能会被多次使用。LocalReport RDLC正在滥用此功能

默认情况下,租赁时间为。。。10分钟!另外,如果有人打了各种各样的电话,等待时间会增加2分钟!因此,它可以随机地在10到20分钟之间,这取决于电话的排列方式。幸运的是,您可以更改此超时发生的时间。不幸的是,每个应用程序域只能设置一次。。。因此,如果您需要PDF生成以外的远程处理,您可能需要另一个运行它的服务,以便更改默认值。为此,您只需在启动时运行以下4行代码:

    LifetimeServices.LeaseTime = TimeSpan.FromSeconds(5);
    LifetimeServices.LeaseManagerPollTime = TimeSpan.FromSeconds(5);
    LifetimeServices.RenewOnCallTime = TimeSpan.FromSeconds(1);
    LifetimeServices.SponsorshipTimeout = TimeSpan.FromSeconds(5);
您将看到内存使用开始上升,然后在几秒钟内您将看到内存开始下降。我花了好几天的时间使用内存分析器来真正追踪这一点,并意识到发生了什么

您不能在using语句中包装ReportViewer(Dispose崩溃),但如果您直接使用LocalReport,则应该能够包装ReportViewer。在处理完之后,如果您想加倍确保正在尽一切努力释放内存,可以调用GC.Collect()

希望这有帮助

编辑


显然,您应该在生成PDF报告后调用GC.Collect(0),否则由于某些原因,内存使用率可能仍然会很高。

内存泄漏的证据是什么?你在测量什么,你看到了什么?您是以32位还是64位进程运行此进程?您在其中执行此操作的流程的性质是什么(是一个长期运行的服务器应用程序,还是一个短期的批处理应用程序)?好奇:为什么要在Using中调用Dispose?另外,问题的实际症状是什么?我把这读作“它不起作用,原因如下”。你能说明你看到了什么和任何错误信息吗?另外,你还可以说明memorystream部分不是问题所在。您是如何确定的?添加了更多信息,主要问题是如果用户调用此函数3次,应用程序将达到>1GB的内存,然后崩溃。这只是一些报告的批处理渲染,一旦它们被渲染并由用户导出或打印,我就不再需要它们在内存中了,不幸的是,我的代码没有处理它们。你尝试过这里发布的解决方案吗?您是否介意分享您可以在哪里添加此代码?我正在使用ASP.net 4.5启动应用程序。在应用程序启动或主程序中。它只能运行一次。