我开发了一个应用程序,它创建了一堆带有sql作为数据的pdf报告。
在此图中,您可以在使用500,100,100和500 PDF文件执行作业时查看此应用程序的已分配空间。
问题是,每个作业后分配的空间增加。所以在某些时候应用程序崩溃了。首先,应用程序需要73476 KB,在上一次报告后我需要230188 KB内存。
将从任务中调用此代码。
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创建,我添加了更多代码。
很多! 马丁
答案 0 :(得分:1)
这听起来像你正在使用的应用程序或库中的内存泄漏。任何实现IDisposable
的东西都应该被处理或包装在一个使用块中。与某些人的看法相反,C#可能会出现内存泄漏,特别是如果您使用包装本机代码的内容。有关内存泄漏可能发生的示例,请参阅this。
另外,请记住内存使用情况以及GC回收的方式因机器而异。 GC不保证在需要之前回收内存,因此虽然有时看起来像是发生了内存泄漏(尤其是在服务器操作系统上运行),但实际上并非如此。这不是这里的情况,因为你得到了OOM但是要考虑的是纯粹上升的记忆并不总是表明泄漏