System.Outofmemoryexception error

Asked

Viewed 2,012 times

1

I don’t know how to solve this problem:

inserir a descrição da imagem aqui

As noted by Marcos Marques this is about the size for each record in total of 4 thousand records. inserir a descrição da imagem aqui

Where can I improve the code:

public ActionResult ExportarPDF(ProcessamentoRegistrosDTO pProcessamentoRegistrosDTO)
        {
            try
            {
                #region :: variáveis ::
                string _nomeArquivo = string.Empty;
                TempData["Id"] = null;
                TempData["DtInicio"] = null;
                TempData["DtFim"] = null;
                TempData["Parametro"] = null;
                TempData["CodigoSituacao"] = null;
                TempData["ServicosId"] = null;
                #endregion

                #region :: executa o filtro da tela ::

                IEnumerable<ProcessamentoRegistros> _processamentoRegistros = null;

                if (pProcessamentoRegistrosDTO.DtInicio != null || pProcessamentoRegistrosDTO.DtFim != null)
                {
                    _processamentoRegistros = _IRepositorio.ListarProcessamentoRegistros()
                                                            .Where(x => x.DataInclusao.Value.Date >= pProcessamentoRegistrosDTO.DtInicio);

                    if (pProcessamentoRegistrosDTO.DtInicio != null && pProcessamentoRegistrosDTO.DtFim != null)
                    {
                        _processamentoRegistros = _processamentoRegistros.Where(x => x.DataInclusao >= pProcessamentoRegistrosDTO.DtInicio
                                                                                && x.DataInclusao.Value.Date <= pProcessamentoRegistrosDTO.DtFim);
                    }
                    else if (pProcessamentoRegistrosDTO.DtInicio != null && pProcessamentoRegistrosDTO.DtFim == null)
                    {
                        _processamentoRegistros = _processamentoRegistros.Where(x => x.DataInclusao.Value.Date >= pProcessamentoRegistrosDTO.DtInicio);
                    }
                    else
                    {
                        _processamentoRegistros = _processamentoRegistros.Where(x => x.DataInclusao.Value.Date <= pProcessamentoRegistrosDTO.DtFim);
                    }
                }
                else
                {
                    var mesAtual = DateTime.Now.Month;
                    _processamentoRegistros = _IRepositorio.ListarProcessamentoRegistros()
                                                        .Where(x => x.DataInclusao.Value.Month == mesAtual);
                }

                if (!string.IsNullOrWhiteSpace(pProcessamentoRegistrosDTO.Parametro))
                    _processamentoRegistros = _processamentoRegistros.Where(x => x.Parametro == pProcessamentoRegistrosDTO.Parametro);

                if (pProcessamentoRegistrosDTO.IdServico > 0)
                    _processamentoRegistros = _processamentoRegistros.Where(x => x.IdServico == pProcessamentoRegistrosDTO.IdServico);

                if (pProcessamentoRegistrosDTO.CodigoSituacao > 0)
                    _processamentoRegistros = _processamentoRegistros.Where(x => x.CodigoSituacao == pProcessamentoRegistrosDTO.CodigoSituacao);

                ServicosRepositorio _repoServicos = new ServicosRepositorio();
                IEnumerable<Servicos> _servicos = _repoServicos.ListarServicos();

                IEnumerable<ProcessamentoRegistrosDTO> _processamentoServico = from prg in _processamentoRegistros
                                                                               join servicos in _servicos on prg.IdServico equals servicos.Id into outServicos
                                                                               from servicos in outServicos.DefaultIfEmpty()
                                                                               select new ProcessamentoRegistrosDTO
                                                                               {
                                                                                   Id = prg.Id,
                                                                                   Parametro = prg.Parametro,
                                                                                   Descricao = servicos.Descricao,
                                                                                   DocumentoHtml = prg.DocumentoHtml,
                                                                                   DocumentoPDF = prg.DocumentoPDF
                                                                               };

                List<ProcessamentoRegistrosDTO> _lstProcessamento = new List<ProcessamentoRegistrosDTO>();
                _lstProcessamento = _processamentoServico.ToList();

                #endregion

                if (_processamentoServico != null && _processamentoServico.Count() > 0)
                {

                    #region :: converte arquivo html para pdf ::
                    List<byte[]> meusPDFs = new List<byte[]>();

                    foreach (var item in _processamentoServico)
                    {
                        _nomeArquivo = "Documento_Fiscal_" + DateTime.Now.ToString().Replace(" ", "_").Replace("/", "_").Replace(":", "_") + ".zip";
                        if (!string.IsNullOrWhiteSpace(item.DocumentoHtml))
                        {
                            MemoryStream file = null;
                            var pechkin = Factory.Create(new GlobalConfig());
                            var _pdf = pechkin.Convert(new ObjectConfig()
                                                        .SetLoadImages(true).SetZoomFactor(1)
                                                        .SetPrintBackground(true)
                                                        .SetScreenMediaType(true)
                                                        .SetCreateExternalLinks(true)
                                                        .SetIntelligentShrinking(true).SetCreateInternalLinks(true)
                                                        .SetAllowLocalContent(true), item.DocumentoHtml.ToString());
                            file = new MemoryStream();
                            file.Write(_pdf, 0, _pdf.Length);
                            meusPDFs.Add(_pdf);
                        }
                    }

                    #endregion
                    string _descricao = string.Empty;

                    #region :: compacta e faz o download do arquivo pdf ::
                    using (var compressedFileStream = new MemoryStream())
                    {
                        //Informações sobre o GetEncoding: https://msdn.microsoft.com/en-us/library/system.text.encodinginfo.getencoding(v=vs.110).aspx
                        Encoding nomeArquivoEncoding = Encoding.GetEncoding(850);
                        using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false, nomeArquivoEncoding))
                        {
                            int i = 0;

                            if (!string.IsNullOrWhiteSpace(_lstProcessamento[i].DocumentoHtml))
                            {
                                foreach (var pdf in meusPDFs)
                                {                                    
                                    _descricao = RemoveSpecialCharacters(RemoveDiacritics(_lstProcessamento[i].Descricao), false);
                                    var zipEntry = zipArchive.CreateEntry(_lstProcessamento[i].Id + "_" + _lstProcessamento[i].Parametro + "_" + _descricao + ".pdf");                                   

                                    using (var originalFileStream = new MemoryStream(pdf))
                                    {
                                        using (var zipEntryStream = zipEntry.Open())
                                        {
                                            originalFileStream.CopyTo(zipEntryStream);
                                        }
                                    }
                                    i++;
                                }
                            }

                        }
                        return new FileContentResult(compressedFileStream.ToArray(), "application/zip") { FileDownloadName = "CPFL Renováveis – Controle de Documentos Fiscais " + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".zip" };
                    }
                    #endregion                    
                }
                else
                {
                    return RedirectToAction("Index", "Documento");
                }

            }
            catch (Exception ex)
            {
                TempData["mensagemErro"] = string.Format("Download não efetuado! " + ex.Message.ToString());
                return RedirectToAction("Index", "Documento");
            }
        }
  • I may be talking pumpkin, but in foreach, try adding a Thread.Sleep(5); at the end, once this solved a problem of mine of Outofmemory.

  • What would be the 5 ? since Thread.Sleep is based on milliseconds, example a second would be Thread.Sleep(1000).

  • Exactly, five milliseconds, it’s a little time for the show to take a breath.

2 answers

3

Actually there are some problems in your code.

Firstly, it is not the responsibility of Controller shoulder all these processing responsibilities. Depending on the volume of information it is important you create an asynchronous queuing and batch processing process.

Another problem is that as there is one Try/catch for all the code, it is more complicated to know in which stretch this exception is being fired. I suggest you add Try/catch at other points where there is access to base to try to identify the specific location that problem occurs (example one for code within #region :: executa o filtro da tela :: other to the code within #region :: converte arquivo html para pdf ::).

But the problem of System.Outofmemoryexception itself occurs when there is not enough memory to continue running a program and can be triggered by any method call or property assignment that requires memory allocation.

There is a point in the code that can be improved where instead (where you are instantiating an object Memorystream in each iteration):

...
foreach (var item in _processamentoServico)
{
    if (!string.IsNullOrWhiteSpace(item.DocumentoHtml))
    {
        MemoryStream file = null;
        var pechkin = Factory.Create(new GlobalConfig());
        var _pdf = pechkin.Convert(new ObjectConfig()
                                    .SetLoadImages(true).SetZoomFactor(1)
                                    .SetPrintBackground(true)
                                    .SetScreenMediaType(true)
                                    .SetCreateExternalLinks(true)
                                    .SetIntelligentShrinking(true).SetCreateInternalLinks(true)
                                    .SetAllowLocalContent(true), item.DocumentoHtml.ToString());
        file = new MemoryStream();
        file.Write(_pdf, 0, _pdf.Length);
        meusPDFs.Add(_pdf);                         
    }
}
...

Use a block using (for this resource to be released via Dispose with each iteration) thus:

...
foreach (var item in _processamentoServico)
{
    using(MemoryStream file = new MemoryStream())
    {
        if (!string.IsNullOrWhiteSpace(item.DocumentoHtml))
        {
            //MemoryStream file = null;
            var pechkin = Factory.Create(new GlobalConfig());
            var _pdf = pechkin.Convert(new ObjectConfig()
                                        .SetLoadImages(true).SetZoomFactor(1)
                                        .SetPrintBackground(true)
                                        .SetScreenMediaType(true)
                                        .SetCreateExternalLinks(true)
                                        .SetIntelligentShrinking(true).SetCreateInternalLinks(true)
                                        .SetAllowLocalContent(true), item.DocumentoHtml.ToString());
            //file = new MemoryStream();
            file.Write(_pdf, 0, _pdf.Length);
            meusPDFs.Add(_pdf);                         
        }
    }
}
...
  • Correct! I will correct and post the result.

  • implemented your suggestion of using the using And at the discretion of comment I found that there were no indices and primary keys in the database tables, however my problem still persists, but there was an improvement: previously could not compress any file and now at least I can compress up to 1,500 files but it is not enough and the error still persists.

  • 1

    So @Adrianosuv, just with the suggested improvement, from 0 to 1,500 files, IE was already very useful. But I made more recommendations, as I put in the answer you have more problems with that code, your controller does more than it should, file processing is not her responsibility, use more Try/catch to see where you’re still popping the bug and treat like you did and found out about the indexes, try to process it asynchronously, processing in a queue, etc, so you have to try to go point by point by analyzing and improving.

  • you can add here some link talking about: tentar processar isso de forma assíncrona, processando em fila, etc

0

Dude, probably the size you’re passing to the.write file..

It’s small. I’m not sure what size you’re getting back with the _pdf.length. But it’s little for what you need.

  • are about 4 thousand record I edited the post and added a print.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.