2

我开发了一个应用程序,它使用 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 分析使用的内存。最常用的空间它没有管理所以我不知道你是罪魁祸首。

ANTS 内存分析器

内存消耗

那么有什么想法吗?

更新,报告将使用 fastreport .net 2013.3 创建,我添加了更多代码。

多谢!马丁

4

1 回答 1

1

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

于 2013-11-25T14:06:39.857 回答