Приложение C# требует больше памяти при каждом вызове
Я разрабатываю приложение, которое создает кучу отчетов в формате PDF с SQL в качестве источника данных.
На этом рисунке вы можете видеть выделенное пространство этого приложения, когда выполняете работу с 500, 100, 100 и 500 файлами PDF.
Проблема в том, что выделенное пространство увеличивается после каждой работы. Так что в какой-то момент приложение вылетает. Сначала приложению нужно 73476 КБ, а после последнего отчета - 230188 КБ.
Этот код будет вызываться из задачи.
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;
}
Я добавил
GC.Collect();
GC.WaitForPendingFinalizers();
но я не большой поклонник, чтобы позвонить в GC сам. И это не помогло против постоянного увеличения использования памяти.
Я попытался проанализировать использованную память с помощью ANTS Memory Profiler. Самым используемым пространством было неуправляемое, так что я не знаю, ты виноват.
Так какие-нибудь идеи?
Обновление, отчет будет создан с fastreport .net 2013.3, и я добавил больше кода.
Большое спасибо! Мартин
1 ответ
Для меня это звучит как утечка памяти в вашем приложении или библиотеках, которые вы используете. Все, что реализует IDisposable
должны быть утилизированы или завернуты в блок для использования. Вопреки мнению некоторых людей, в C# возможна утечка памяти, особенно если вы используете что-то, что оборачивает нативный код. Посмотрите это для примера того, как может произойти утечка памяти.
Кроме того, помните, что использование памяти и как GC восстанавливает, который зависит от машины. GC не гарантирует восстановление памяти до тех пор, пока она не понадобится, поэтому, хотя иногда это может выглядеть как утечка памяти (особенно при работе в серверных операционных системах), на самом деле это не так. Это не тот случай, когда вы получаете OOM, но стоит подумать о том, что чисто растущая память не всегда является признаком утечки