WPF Crystal报告内存泄漏问题

时间:2018-11-15 05:42:58

标签: c# wpf crystal-reports report

我在wpf中遇到了Crystal报表问题,尽管一段时间后Crystal报表查看器停止再次加载Crystal报表,并且它抛出以下异常,但在我们的应用程序中不断打开报表:

  

加载报告失败。   不支持的操作。 JRC引擎处理的文档无法在C ++堆栈中打开。

异常详细信息为:

  

CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened()      在CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(字符串文件名,OpenReportMethod openMethod,Int16 parentJob)      在CrystalDecisions.CrystalReports.Engine.ReportClass.Load(String reportName,OpenReportMethod openMethod,Int16 parentJob)      在CrystalDecisions.CrystalReports.Engine.ReportDocument.EnsureLoadReport()      在CrystalDecisions.CrystalReports.Engine.ReportDocument.SetDataSourceInternal(Object val,Type type)      在CrystalDecisions.CrystalReports.Engine.ReportDocument.SetDataSource(DataSet dataSet)**

在这段时间内监视任务管理器时,我注意到,我在关闭Crystal Report Viewer窗口之前放置的Crystal Reports并没有释放报告/报告查看器的已用内存。这实际上是导致问题的原因。还有其他方法可以正确处理水晶报表对象吗?

这是连续加载报告时发生异常的屏幕截图: Image

这是我的代码块

CReportManager.cs

private bool GenerateReport(object oValue, bool bNeedPreview)
{
    Reports.crtSampleReport ocrtSample = null ;
    System.Drawing.Printing.PrintDocument doctoprint = null ;

    // its a usercontrol placed on this assembly
    PopUp.ucManagePrintPreview oPrintPreview = null;

    try
    {
        //pass the data to feed the report from other classes ( from same / different assembly ) 
        System.Data.DataSet dsPrintData = (System.Data.DataSet)oValue;

        if (dsPrintData == null || dsPrintData.Tables[2].Rows.Count == 0)
            throw new GOGGeneralHelpers.CGOGCustomException(
                "Print Data is Null", "No Data Available To Print", GOGGeneralHelpers.EnumLogType.ERR);

        ocrtSample = new Reports.crtSampleReport( ) ;
        ocrtSample.SetDataSource( dsPrintData ) ;
        ocrtSample.PrintOptions.PaperOrientation = CrystalDecisions.Shared.PaperOrientation.Portrait;

        System.Windows.Forms.DialogResult enDialogResult = System.Windows.Forms.DialogResult.OK;

        if (bNeedPreview)
        {     
            // if user want to view the preview before printing the report then its loads 
            // to a crystal report viewer placed on a usercontrol on this same assembly

            oPrintPreview = new PopUp.ucManagePrintPreview();
            oPrintPreview.FillReport( ocrtSample ) ;

            //a Window object placed on another assembly
            EHRPresentationBaseClassLibrary.Popups.PopupWindow
                        oPopupWindow = new EHRPresentationBaseClassLibrary.Popups.PopupWindow( ) ;

            //add the user control object (with crystal report viewer) to this window object            
            oPopupWindow.SetPopupPage( oPrintPreview ) ;
            oPopupWindow.Title = "Print Preview";
            oPopupWindow.Width = GOGPresentationCommonClassesLibrary.CCurrentAppSettings.CurrentAppSettings.PageWidth * .9;
            oPopupWindow.Height = System.Windows.SystemParameters.PrimaryScreenHeight * .8;
            oPopupWindow.ShowDialog();
            enDialogResult = oPrintPreview.PageResult ;                   
        }

        if (enDialogResult == System.Windows.Forms.DialogResult.Cancel
                    || enDialogResult == System.Windows.Forms.DialogResult.None) return true;

        //// Read printer name from a config file ///////////////////////

        System.IO.StreamReader oReader = System.IO.File.OpenText("PrintConfig.bat");
        string sPrinterName = oReader.ReadLine();
        oReader.Close();

        doctoprint = new System.Drawing.Printing.PrintDocument( ) ;
        doctoprint.PrinterSettings.PrinterName = sPrinterName ;

        //validate readed printer name is valid or not
        if ( !doctoprint.PrinterSettings.IsValid )
            throw new GOGGeneralHelpers.CGOGCustomException(
                "Selected Printer is not Valid", "Selected Printer is not Valid", GOGGeneralHelpers.EnumLogType.ERR ) ;

        ///////////////////////////////////////////////////////////////

        ocrtSample.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.PaperA4;

        ocrtSample.PrintOptions.PrinterName = sPrinterName;
        ocrtSample.PrintToPrinter(0, false, 0, 0);
        bReturn = true ;
    }
    catch (GOGGeneralHelpers.CGOGCustomException oCGOGCustomException)
    {                
        GOGPresentationCommonClassesLibrary.CApplicationHelper.
                    ApplicationHelper.ShowUserMessage(oCGOGCustomException, false, false);
        GOGGeneralHelpers.CGOGClientLogWriter.ClientLogWriter.WriteLog(oCGOGCustomException);
    }
    catch (System.Exception oException)
    {
        //Write to log file
        GOGGeneralHelpers.CGOGClientLogWriter.ClientLogWriter.WriteLog(oException);

        //Showing message to user
        GOGPresentationCommonClassesLibrary.CApplicationHelper.
                    ApplicationHelper.ShowUserMessage("Unexpected error on printing", oException, false, false);
    }

    // disposing the crystal report object
    // here is the issue its not releasing consumed memeory
    ocrtSample.Close(); 
    ocrtSample.Dispose();
    ocrtSample = null;

    doctoprint.Dispose();
    doctoprint = null;

    // disposing the crystal report viewer object
    oPrintPreview.ClearReportViewer();

    //this is also not working
    System.GC.Collect();
}

PopUp.ucManagePrintPreview.cs

//Function to load selected report to crystal report viewer
public void FillReport(CrystalDecisions.CrystalReports.Engine.ReportClass oReport) 
{
    MyCrystalReportViewer.ReportSource = oReport;
    MyCrystalReportViewer.ShowPrintButton = true;
}

//Function for dispose crystal report viewer object 
public void ClearReportViewer()
{
    MyCrystalReportViewer.ReportSource = null;
    MyCrystalReportViewer.Dispose();            
}

1 个答案:

答案 0 :(得分:0)

我认为真正的问题是例外。内存由GC处理。 deletefree的非托管方面可能没有多少,这就是为什么当释放几个字节时任务管理器中的内存可能不会改变的原因。

除此之外,我观察到只有在Crystal-Reports找不到您提供的报告(文件)时才发生此异常,类似于FileNotFoundException。您提供的stacktrace还显示了对各种CR内部Load方法的调用。