gpt4 book ai didi

c# - RDLC 内存泄漏

转载 作者:行者123 更新时间:2023-12-04 16:29:35 28 4
gpt4 key购买 nike

在我的应用程序 (.NET Framework 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 被称为添加 20-30mb,并且在我关闭应用程序之前它们永远不会下降。我确定使用 MemoryStream不是问题,因为即使评论我仍然会在内存中获得 200mb-250mb 永远不会被释放。这很糟糕,因为在运行此应用程序 3-4 次后,它会达到 >1GB,直到它甚至不再运行。我也尝试手动调用 GarbageCollector但没有用。该应用程序是 32 位的。

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

最佳答案

我有一个真正的解决方案,可以解释原因!

事实证明,这里的 LocalReport 使用 .NET Remoting 动态创建子应用程序域并运行报告,以避免内部某处的泄漏。然后我们注意到,最终,报告将在 10 到 20 分钟后释放所有内存。对于生成大量 PDF 的人来说,这是行不通的。然而,这里的关键是他们正在使用 .NET Remoting。 Remoting 的关键部分之一是所谓的“租赁”。租赁意味着它将保留那个编码(marshal)对象一段时间,因为远程处理通常设置起来很昂贵,而且它可能会被多次使用。 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);

您会看到内存使用量开始上升,然后在几秒钟内您应该会看到内存开始回落。我花了几天的时间使用内存分析器来真正跟踪并意识到发生了什么。

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

希望这可以帮助!

编辑

显然,您应该在生成 PDF 报告后调用 GC.Collect(0) ,否则由于某种原因,内存使用量似乎仍然很高。

关于c# - RDLC 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53229762/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com