Skip to Content
0

Memory Leak in ReportDocument / Crystal Report Viewer CR for VS 13_0_19

Jan 31, 2017 at 03:41 PM

286

avatar image
Former Member

I am seeing a nasty memory leak when loading a ReportDocument and then running the report using the crystal report viewer. The code I am using is below. I just updated to 13.0.19 in hopes that it fixed the issue and still am having problems. My versions on my references show 13.0.2000.0. My report form is just a winform with the viewer docked inside. I even call the following in the dispose. I am running in .net 4.5.1

crystalReportViewer.ReportSource = null;
crystalReportViewer.Dispose();
crystalReportViewer = null;

Before Report ran and loaded

After report loaded and showing in viewer

After all disposes, null assignments, and GC calls

        private void runReportButton_Click(object sender, EventArgs e)
        {
            try
            {
                if (reportSelector.SelectedIndex != -1)
                {
                    reportFolderPath = "reports";


                    //Get report
                    ReportDocument doc = new ReportDocument();
                    doc.Load(reportFolderPath + "\\" + 
reportSelector.SelectedItem);

                    if (useTimeCheckBox.Checked)
                        doc.SetParameterValue("ReportDate", timePicker.Value);

                    //Set parameters
                    if (!string.IsNullOrWhiteSpace(testNumberTextBox.Text))
                        doc.SetParameterValue("TestNumber", int.Parse(testNumberTextBox.Text));


                    if (cellNumberSelector.SelectedValue != null && (int)cellNumberSelector.SelectedValue != -1)
                        doc.SetParameterValue("CellNumber", cellNumberSelector.SelectedValue);


                    if (soNameSelector.SelectedValue != null && (int)soNameSelector.SelectedValue != -1)
                        doc.SetParameterValue("soName", soNameSelector.SelectedValue);


                    if (seNameSelector.SelectedValue != null && (int)seNameSelector.SelectedValue != -1)
                        doc.SetParameterValue("SeName", seNameSelector.SelectedValue);


                    if (serialSelector.SelectedValue != null && (int)serialSelector.SelectedValue != -1)
                        doc.SetParameterValue("Serial", serialSelector.SelectedValue);


                    if (operatorSelector.SelectedValue != null && (int)operatorSelector.SelectedValue != -1)
                        doc.SetParameterValue("Operator", operatorSelector.SelectedValue);


                    if (vehicleSelector.SelectedValue != null && (int)vehicleSelector.SelectedValue != -1)
                        doc.SetParameterValue("Vehicle", vehicleSelector.SelectedValue);


                    //Add a default value to parameters so the report will generate when optional parameters do no have values
                    for (int ii = 0; ii < doc.ParameterFields.Count; ii++)
                    {
                        ParameterDiscreteValue numVal = new ParameterDiscreteValue();
                        numVal.Value = default(int);


                        ParameterDiscreteValue dateVal = new ParameterDiscreteValue();
                        dateVal.Value = default(DateTime);


                        ParameterDiscreteValue stringVal = new ParameterDiscreteValue();
                        stringVal.Value = string.Empty;


                        if (doc.ParameterFields[ii].HasCurrentValue)
                            doc.SetParameterValue(ii, doc.ParameterFields[ii].CurrentValues[0]);
                        else
                        {
                            if (doc.ParameterFields[ii].ReportParameterType == ParameterType.ReportParameter)
                            {
                                if (doc.ParameterFields[ii].ReportName == "")
                                {
                                    if (doc.ParameterFields[ii].ParameterValueType == ParameterValueKind.StringParameter)
                                        doc.ParameterFields[ii].CurrentValues.Insert(0, stringVal);
                                    if (doc.ParameterFields[ii].ParameterValueType == ParameterValueKind.NumberParameter)
                                        doc.ParameterFields[ii].CurrentValues.Insert(0, numVal);
                                    if (doc.ParameterFields[ii].ParameterValueType == ParameterValueKind.DateTimeParameter)
                                        doc.ParameterFields[ii].CurrentValues.Insert(0, dateVal);
                                }
                            }
                        }
                    }


                    //Test database connection
                    using (SqlConnection connection = dbHelper.GetDatabaseConnection())
                    {
                        connection.Open();
                    }


                    //setup database settings for the report
                    doc.DataSourceConnections[0].SetConnection(dbSettings.Host, dbSettings.Name, dbSettings.UseUserCredentials);

                    if (!dbSettings.UseUserCredentials)
                    {
                        doc.DataSourceConnections[0].SetLogon(dbSettings.Username, EncryptionHelper.ConvertToUnsecureString(dbSettings.Password));
                    }

                    crDoc = doc;


                    Thread t = new Thread(ShowReport);
                    t.Start();
                }
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }


        private void ShowReport()
        {
            //Setup and show the crystal report viewer
            try
            {
                ReportViewerForm form = new ReportViewerForm();

                form.ReportDoc = crDoc;

                form.ShowDialog();
            }
            catch(Exception ex)
            {
                MessageBox.Show("Something happened. " + ex.ToString());
            }
            finally
            {
                //Close and dispose the document
                crDoc.Close();
                crDoc.Dispose();
                crDoc = null;

                //Cleanup crystal report's mess in memory
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
            }
        }
10 |10000 characters needed characters left characters exceeded
* Please Login or Register to Answer, Follow or Comment.

2 Answers

Best Answer
Don Williams
Mar 16, 2017 at 08:01 PM
0

Hi Jason,

CR has a lot of dependencies on third party dll's, .NET Framework, Printer drivers, GDIPlus, USP10 to name a few.

Make sure when tracking these leaks it's not just the CR runtime that is leaking.

Try a report with no printer checked on, no DB connections and just a simple text object in the report with "hello World" in it. No parameters or formula or anything that could rely on Java etc.

And it's the nature of Windows to not close/dispose of dll's for some time even when the App is idle. Try waiting for an hour and see if the memory decreases also.

And of course when the app closes it should completely release ALL memory attached. It's the nature of Windows.

DEV is very vigilant at cleaning any whole found, within reason, a few K here and there is not work the time spent finding it but they do as much as they can.

I'll talk to DEV and see what kind of scan they do do for leaks....

Don

Show 2 Share
10 |10000 characters needed characters left characters exceeded
Former Member

Hi Don,

I find your answer of "a few K here and there is not work the time spent finding it but they do as much as they can." pretty distressing when we are talking about memory leaks.

"A few K here and there" ends up causing an app to crash with an out of memory exception.

How is anyone supposed to sell that answer?

"Just restart the app every few hours" ?

0
Former Member

This is my problem. This software is going to be in a test facility that will run multiple reports on a machine a day and leave this machine on for months. If this memory is not cleaned up, it is going to crash the system and then I will have to be the one to explain why they have to restart a machine that is collecting data.

0
Don Williams
Mar 24, 2017 at 04:15 PM
0

Create a Batch or script file to it cycles the app automatically once a day or more if required.

Share
10 |10000 characters needed characters left characters exceeded