cancel
Showing results for 
Search instead for 
Did you mean: 

CR Memory Usage and Release

Former Member
0 Kudos

Our program is a WPF clickonce app built with VS2010. Uses the CR Engine/Shared 13.0.2000 dll and WPFCRViewer 13.0.3500 v2.0.50727. Reports are created in full stand alone version of CR 2008. Viewer does a load method with network share path to rpt file chosen.

We previously had another app (win forms VS2008 CR2008) that basically acted the same way with resources and are trying to upgrade it to VS2010 WPF for various reasons.

We have a tab control that gets dynamic tab items.

The tab items content is set to an instance of a custom user control that consists mainly of a WPFCRViewer.

Each tab that is created jumps up task mngr reported memory usage by 10 MB +/-.

When I close the report viewer tab it only regains about 1MB per tab closed.

So after a couple hours of running reports the memory usage goes up to the hundreds of MB and eventually we get out of memory errors on some computers.

Here is how the ReportDocumnt class is supposed to be releasing the resources.


tabcontrol.items.remove(tabItem);

within the UserControl class I have the following ReportDocument IDisposable class that is supposed to clean up the resources.


public sealed class CrystalReportDocument : ReportDocument, IDisposable
        {

            /// <summary>
            /// Frees resources used
            /// </summary>
            public new void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
                base.Dispose();
            }

            private void CleanGlobalEvents()
            {
                Delegate domainUnloadDelegate = (Delegate)typeof(AppDomain).GetField("_domainUnload",
                   BindingFlags.Instance | BindingFlags.NonPublic).GetValue(AppDomain.CurrentDomain);

                Delegate[] invocationList = domainUnloadDelegate.GetInvocationList();
                Delegate ev;


                for (short i = 0; i < invocationList.Length; i++)
                {
                    ev = invocationList<i>;
                    if (ev.Target != null && ev.Target.Equals(this))
                    {
                        AppDomain.CurrentDomain.DomainUnload -= (EventHandler)ev;
                    }

                }


                Delegate processExitDelegate = (Delegate)typeof(AppDomain).GetField("_processExit",
                   BindingFlags.Instance | BindingFlags.NonPublic).GetValue(AppDomain.CurrentDomain);

                invocationList = processExitDelegate.GetInvocationList();

                for (short i = 0; i < invocationList.Length; i++)
                {
                    ev = invocationList<i>;
                    if (ev.Target != null && ev.Target.Equals(this))
                    {
                        AppDomain.CurrentDomain.ProcessExit -= (EventHandler)ev;

                    }
                }
            }


            /// <summary>
            /// Cleans up resources
            /// </summary>
            /// <param name="disposing"></param>
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    this.Close();
                }
                this.CleanGlobalEvents();
                base.Dispose(disposing);
            }

            /// <summary>
            /// Destructs object
            /// </summary>
            ~CrystalReportDocument()
            {
                // Simply call Dispose(false).
                Dispose(false);
            }

        }

Please help, I would like to rool out this app but not if it will crash from memory usage.

Accepted Solutions (1)

Accepted Solutions (1)

former_member183750
Active Contributor
0 Kudos

It looks to me like on each tab view you are instantiating a new report document. Unless you specifically close and dispose this document when you do not need it anymore (on navigate way from the tab(?)), these reports stay in memory until the app is closed.

From your code I am not sure that you are disposing each report as you go(?).

Ludek

Follow us on Twitter http://twitter.com/SAPCRNetSup

Got Enhancement ideas? Try the [SAP Idea Place|https://ideas.sap.com/community/products_and_solutions/crystalreports]

Former Member
0 Kudos

Honestly I have tried many ways with no luck keeping more and more memory from being consumed.

The class I included extends ReportDocument and calls dispose as well as releases event handlers and global resources but I believe it was written for an older version of CrystalReportViewer.

I have tried also simply calling close and dispose for the ReportDocument instance when each tab is closed.

No matter what I do if the user views several reports the memory usage keeps growing and growing.

The application consists of nothing more than a light shell and a tab control that gets a instance of the report viewer for each tab.

The tabs have close buttons and when one is closed I call close and dispose on the report/viewer instance for the closing tab with no luck.

I have read in many other places that CrystalReportViewers are known for "memory leaks" is this true or is there something else I can try?

using VS2010 click once

reports made in stand alone version of CR 2008

viewer is WPFCRViewer

.NET 4 extended in C#

clients use CRRuntime_32bit_13_0_1.msi

UserControl Class consists of:

(this example ommits the extended report documnet class)


        private ReportDocument cr = null;
        private ConnectionInfo ci = null;
        private ViewerCore vc = null;
        public ControlReportViewer(string reportPath)
        {
            InitializeComponent();            vc = crViewer.ViewerCore;
            cr = new ReportDocument();
            cr.Load(reportPath, OpenReportMethod.OpenReportByTempCopy);

            ci = new ConnectionInfo();
            ci.DatabaseName = ".......";
            ci.ServerName = "......";
            ci.UserID = "......";
            ci.Password = "......";
            ci.IntegratedSecurity = false;

            foreach (CrystalDecisions.CrystalReports.Engine.Table t in cr.Database.Tables)
            {
                TableLogOnInfo tbloginfo = t.LogOnInfo;
                tbloginfo.ConnectionInfo = ci;
                t.ApplyLogOnInfo(tbloginfo);
                tbloginfo = null;
            }

            vc.ReportSource = cr;
        }

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            if (cr != null) cr.Close();
            if (cr != null) cr.Dispose();
            
            ci = null;
            vc = null;
        }

former_member183750
Active Contributor
0 Kudos

If and when I have the time, I try to test things like this. Unfortunately, the time is not there right now. That leaves us with two options;

1) Create a [phone case|http://store.businessobjects.com/store/bobjamer/en_US/pd/productID.98078100?resid=S6I@hgoHAkEAAGsiyVkAAAAR&rests=1282226845369] and that will get the attention for a test

2) Create a simple sample app that demos the issue (save data report(s)). If I can get the app from you I should be able to get enough time to reproduce the issue, do some investigating as to the causes and possible ways out of this and if need be, escalate for a fix.

- Ludek

Former Member
0 Kudos

I cant really make a project to give you to exactly replicate it since our viewer uses local network report files (
local-server\report-x.rpt) etc...

Can I just ask what the expected result of memory usage (not exact numbers just in general) would be for a program that uses Load() with report files from a network path.

(e.g. cr.Load(reportPath, OpenReportMethod.OpenReportByDefault);)

When the application opens (app.xaml.cs) opens a dummy report and exports (ExportToDisk()) it to temp location to preload assemblies also.

The program saves a local copy if it doesn't already exist locally in the users temp folder to save time for future loading.

The viewers close()/dispose() is called but I am not seeing any memory freed at all it just keeps accumulating.

I just want to know if I am wrong in assuming the memory usage reported should drop after unloading the report document and viewer instances.

former_member183750
Active Contributor
0 Kudos

Jump of 10MB per report sounds quite normal. You may even see the memory increase to 20 or 30 or 40 MB as you run the reports even though you call .Close and .Dispose after each report. But eventually (and usually after no more than 2 or 3 reports) the memory will return back to about 10MB - never back to the starting 1MB as .Close and .Dispose only clears the report object. It does not unload the CR runtime. That will only happen on close of the actual project.

Re. sample app. I really do not need your reports as such. And actually the following may be even a better test;

Create two or three report with just a text box in the page header; report1 for the 1st report, report2 for the second report and report3. No database connection needed. Create a new simple project and run these reports. Do you see the same memory issue?

- Ludek

Answers (0)