C# CrystalReports报告数据库连接的文档内存泄漏
在过去的几天里,我一直在研究这个问题,但我似乎没有弄明白 我有一个C# CrystalReports报告数据库连接的文档内存泄漏,c#,.net,winforms,memory-leaks,crystal-reports,C#,.net,Winforms,Memory Leaks,Crystal Reports,在过去的几天里,我一直在研究这个问题,但我似乎没有弄明白 我有一个c#WinForms应用程序,它使用ReportDocument加载报表并将其放入Crystal报表查看器,以便用户可以预览它。其目的是预览不同的统计信息,并且表单永远不会关闭。有一个计时器可以运行并将不同的报告加载到查看器中 在这种情况下,内存使用和句柄(我可以在任务管理器中看到它们)不断增加。当应用程序启动时,它使用大约30 MB,当它运行10分钟时,它使用大约200 MB,并且它不断增加 我在互联网上读了很多关于这个问题的文
c#
WinForms
应用程序,它使用ReportDocument
加载报表并将其放入Crystal报表查看器,以便用户可以预览它。其目的是预览不同的统计信息,并且表单永远不会关闭。有一个计时器可以运行并将不同的报告加载到查看器中
在这种情况下,内存使用和句柄(我可以在任务管理器中看到它们)不断增加。当应用程序启动时,它使用大约30 MB,当它运行10分钟时,它使用大约200 MB,并且它不断增加
我在互联网上读了很多关于这个问题的文章,发现ReportDocument
和查看器都需要关闭和处理。不幸的是,这并不能解决问题。报告中的连接类型为OLE DB(ADO)
,因为数据是从SQL Server
数据库检索的
简单地说,Form1有一个计时器,当计时器过期时,它会处理Crystal Reports Viewer
,并调用垃圾收集器。然后加载新报告
这是我的示例代码
表格1:
private ReportDocument rpt;
private void timer2_Tick(object sender, EventArgs e)
{
timer2.Enabled = false;
try
{
panel1.Hide();
if (rpt != null)
{
foreach (Table t in rpd.Database.Tables)
t.Dispose();
rpt.Close();
rpt.Dispose();
rpt = null;
GC.Collect();
}
panel1.Controls.Remove(CRVviewer);
if (CRVviewer != null)
{
CRVviewer.Dispose();
GC.Collect();
}
// The problem starts from here:
var report = navigationbar1.CurrentNode;
rpt = new ReportDocument();
rpt.Load(@report.Path, OpenReportMethod.OpenReportByDefault);
rpt.ReportOptions.EnableSaveDataWithReport = false;
rpt.SetDatabaseLogon(report.UserId, report.Password);
rpt.VerifyDatabase();
// It ends here
CRVviewer = new CrystalReportViewer();
CRVviewer.ReportSource = rpt;
CRVviewer.ShowLastPage();
pagecount = CRVviewer.GetCurrentPageNumber();
CRVviewer.ShowFirstPage();
panel1.Controls.Add(CRVviewer);
this.Update();
}
catch(Exception ex)
{
ProcessErrors(ex);
}
finally
{
timer2.Enabled = true;
}
}
问题来自数据库连接,因为如果我加载本地报告,它工作正常。但是我做错了什么呢?使用Crystal Report很难清理它在内存中造成的混乱。(不触犯SAP)
您必须首先关闭并处理ReportDocument
rpt.Close();
rpt.Dispose();
然后将空值分配给ReportViewer
并进行处置
CRViewer.ReportSource=null;
CRViewer.Dispose();
CRViewer=null;
最后,您必须进行两次GC收集
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
请注意,通常不建议调用GC.Collect(),但有时当内存太大时,第三方COM组件(如crystal report)在正确处置方面遇到问题,我们可能不得不这样做
我找到了解决办法。100%工作。请安装crystal report运行时版本13\u 0\u 26。它为我修好了。生成100份报告最多只需100 mb。
新版本可能与您的nuget软件包不兼容,因此请相应地更新您的引用。谢谢,内存使用情况现在似乎很好,但任务管理器中的句柄一直在增加。编辑:经过更多测试,内存使用情况仍在增加。您可以尝试使用类似[dotMemory]的内存探查器()这一款使用方便,免费试用5天。当我在Crystal reports中遇到类似的内存问题时,我用这个工具解决了我的内存问题。此外,您还希望密切关注任何已订阅的事件,特别是如果您在这些事件中有任何crystal report参考,那么您可以适当地取消订阅。我将尝试运行您的代码,看看是否可以找到任何其他问题?这是完整的代码吗?在应用程序运行超过20小时后,我可以确认上述解决方案是否有效。可能这一行
GC.WaitForPendingFinalizers()代码>产生了巨大的变化。我整天都在试图让这个查看器释放DB连接。这似乎奏效了。非常感谢。