Resource problem (memory usage increased)

edited 2:28AM in FastReport .NET
It looks that the memory usage of FastReport is increasing without given it (totaly) back when the application is not busy with printing.
In the taskmanager the memory is increasing and descreasing but the values are growing over the time.

I have included a zip file with a test.exe and some files (report, xml) that are needed for the test app.
I did also included the source of the test application. It is a simplified example how we print large amount of prints.
(you will find it also below this thread)

When you unzip the file into a folder and start the test.exe you have to enter the folder where the files are copied (ex. C:\test).
(it is a test app without error checks)

When the app is running, it will do 10000 PrintPrepares, not real prints, of the same report.
When you wait until there are over 1000 reports prepared I think you will what I mean.

Question: is there a problem in the FastReport engine that is given back resources well? Or did I make somewhere a mistake ?

Thanks
Hans

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using FastReport;
using FastReport.Utils;
using System.Threading;

namespace WindowsFormsApplication4
{
    public partial class Form1 : Form
    {
        private delegate void UpdateProgress();
        int _countPrints;
        Boolean _isStopped;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart jobProcessWorkFiles = new ThreadStart(PrintRun);
            Thread threadProcessWorkFiles = new Thread(jobProcessWorkFiles);
            threadProcessWorkFiles.Start();
        }

        private void PrintRun()
        {
            string pathFiles = textBox1.Text;

            for (int i = 0; i < 10000 && !_isStopped; i++)
            {

                using (Report report1 = new Report())
                {
                    DataSet ds = new DataSet();
                    ds.ReadXml(@pathFiles + "\\Example45.xml");
                    report1.Load(@pathFiles + "\\FR000045.FRX");
                    DataTable dtData = new DataTable();
                    dtData.ReadXmlSchema(@pathFiles + "\\fr000045.xsd");

                    // Create a new CultureInfo for the United Kingdom.
                    System.Globalization.CultureInfo myCultureInfo = new System.Globalization.CultureInfo("en-gb");
                    dtData.Locale = myCultureInfo;

                    DataRow[] copyRows = ds.Tables["Table"].Select();
                    foreach (DataRow copyRow in copyRows)
                        dtData.ImportRow(copyRow);
                    if (dtData.Rows.Count != 0)
                    {
                        try
                        {
                            report1.RegisterData(dtData, "Table");
                        }
                        catch (Exception ex)
                        {
                            return;
                        }
                    }
                    copyRows = null;
                    report1.PrintSettings.ShowDialog = false;
                    Config.ReportSettings.ShowProgress = false;
                    if (report1.Prepare(false))
                    {
                        //report1.PrintPrepared();
                        UpdateEditMask();
                    }
                }
            }
        }
        private void UpdateEditMask()
        {
            if (maskedTextBox1.InvokeRequired)
            {
                Invoke(new UpdateProgress(UpdateEditMask));
                return;
            }
            _countPrints++;
            maskedTextBox1.Text = _countPrints.ToString();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            _isStopped = true;
        }
    }
}

Comments

  • edited 2:28AM
    The attached archive is damaged, could you send me a copy to tz@fast-report.com?
  • edited 2:28AM
    Hi Alex,

    Did you find some solution about this problem? I have similar problem like Hans.

    Robert
  • edited 2:28AM
    Hello,

    Here is the solution: create new AppDomain and execute the report in it. When you no longer need the report, unload the domain. Creating/unloading domains is rather slow (10x slower than just creating a new instance of report), that's why we didn't implement that method in FastReport. But, at the application level, you may optimize this process. You may create a domain and use it, say, 1000 times, then unload it. In this case the performance hit will not so big.

    Here is the example:
    private void PrintRun()
    {
        AppDomain appDomain = null;
        // domain time-to-live
        int domainTTL = 0;
    
        for (int i = 0; i < 10000 && !_isStopped; i++)
        {
            if (appDomain == null)
            {
                AppDomainSetup appDomainSetup = new AppDomainSetup();
                appDomainSetup.ShadowCopyFiles = "false";
                appDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
                appDomain = AppDomain.CreateDomain("new domain", AppDomain.CurrentDomain.Evidence, appDomainSetup);
            }
    
            Worker worker = appDomain.CreateInstanceAndUnwrap(
                this.GetType().Assembly.FullName, typeof(Worker).FullName) as Worker;
    
            worker.Print();
            UpdateEditMask();
    
            // unload the domain after 1000times of use
            domainTTL++;
            if (domainTTL > 1000)
            {
                AppDomain.Unload(appDomain);
                appDomain = null;
                domainTTL = 0;
            }
    
            GC.Collect();
        }
    }
    
    // this class is doing actual printing
    public class Worker : MarshalByRefObject
    {
        public void Print()
        {
            using (Report report = new Report())
            using (DataSet ds = new DataSet())
            {
                ds.ReadXml("Example45.xml");
                ds.ReadXmlSchema("fr000045.xsd");
                report.Load("1.frx");
                report.RegisterData(ds, "Data");
    
                Config.ReportSettings.ShowProgress = false;
                report.Prepare();
            }
        }
    }
    

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.