I develop an application that creates a bunch of pdf reports with a sql as data srouce.
In this graphic you can see the allocated space of this application when do a job with 500,100,100 and 500 PDF Files.
The Problem is, that the allocated space increase after each job. So at some point the application crashes. At first the application needs 73476 KB and after the last report i need 230188 KB Memory.
This Code will be called from a Task.
public static bool Run(string id, SessionDescription session, IProgress<ProgressState> progress = null, CancellationToken cancellationToken = new CancellationToken(), Func<string,bool> prepareTargetFolder = null)
{
SessionDescription.Validate(session);
var pageLibrary = CreatePageLibrary(id, session.FrxFiles.Select(f => f.FullPath), session.PageDescriptions, session.Mappings);
session.PageDescriptions = CompletePageDescriptionDataSourceNames(session.PageDescriptions, pageLibrary);
if (cancellationToken.IsCancellationRequested) return false;
try
{
var parallelOptions = new ParallelOptions() {MaxDegreeOfParallelism = 1, CancellationToken = cancellationToken};
long count = 0;
if (session.Jobs.Count > 0)
{
var job = session.Jobs.First();
job.TargetSpec = TargetDescription.ComposeFullPath(session.Target ?? new TargetDescription(), job.TargetSpec, job.DataSourceSet, 0);
if (prepareTargetFolder != null && !prepareTargetFolder(Path.GetDirectoryName(job.TargetSpec)))
return false;
ProcessOneDocument(id, session.PageDescriptions, session.PageCompositions, pageLibrary, job.DataSourceSet, session.BackpageName, job.TargetSpec);
ProcessProgress(progress, ref count, session.Jobs.Count, job.TargetSpec);
}
Parallel.For(1, session.Jobs.Count, parallelOptions, index =>
{
var job = session.Jobs[index];
ProcessJob(id, index, job, session, pageLibrary);
ProcessProgress(progress, ref count, session.Jobs.Count, job.TargetSpec);
});
}
catch (OperationCanceledException)
{
return false;
}
catch (AggregateException exception)
{
throw exception.Flatten();
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
return true;
}
I added the
GC.Collect();
GC.WaitForPendingFinalizers();
but I'm not a big fan to call the GC myself. And it didn't help against the steady increase of memory usage.
I did try to analyse the used memory with ANTS Memory Profiler. The most used space it unmanaged so I don't know you is to blame.
So any Ideas?
Update, report will be created with fastreport .net 2013.3 and i added more code.
Thx a lot! Martin
This sounds to me like a memory leak in your application or libraries you are using. Anything that implements IDisposable
should be either disposed or wrapped in a using block. Contrary to some people's belief, it is possible to have a memory leak with C#, especially if you use something that wraps native code. See this for an example of how a memory leak could occur.
Also, remember that memory usage and how the GC reclaims that varies per machine. The GC isn't guaranteed to reclaim memory until its needed, so while it may sometimes look like a memory leak is occuring (especially running on server operating systems), it actually isn't. Thats not the case here since you are getting OOM but it is something to think about that purely rising memory isn't always an indication of a leak