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连接。这似乎奏效了。非常感谢。