Search code examples
c#.netiis-7.5itext

ITextSharp - After creating PDF File, it stucks in IIS Worker Process and can't be moved


I have a code that merges certain number of PDF files into a single PDF file using ITextSharp library.

The code works fine and it creates that single pdf file every time I debug my code in visual studio. It also works fine for certain number of such requests. But, when I run it in an automated test case for 250 such requests, 2 or 3 out of those 250 requests fail due to the generated single PDF file being not yet released from IIS Worker Process.

When I tried a test case with 2000 requests, 7 out of those 2000 requests failed due to the generated file being stuck in the IIS Process.

I have tried closing/releasing all objects though. Please help me find out the mistake. Here is the code:

List<PdfReader> pdfReaders = new List<PdfReader>();
int totalPageCount = 0;
Document document = null;
PdfWriter pdfWriter = null;

try
{
    document = new Document();
    pdfWriter = PdfWriter.GetInstance(document, new FileStream(destinationFilePath, FileMode.Create));
    document.Open();

PdfContentByte contentByte = pdfWriter.DirectContent;
PdfImportedPage page = null;
int rotation = 0;

foreach (string filePath in sourceFiles)
{
    PdfReader pdfReader = new PdfReader(filePath);
    pdfReaders.Add(pdfReader);
    totalPageCount = pdfReader.NumberOfPages;

    //iterate throw each page of current source pdf file
    for (int currentPageNumber = 1; currentPageNumber <= totalPageCount; currentPageNumber++)
    {
        document.SetPageSize(pdfReader.GetPageSizeWithRotation(currentPageNumber));
        document.NewPage();
        page = pdfWriter.GetImportedPage(pdfReader, currentPageNumber);
        rotation = pdfReader.GetPageRotation(currentPageNumber);
        if (rotation == 90 || rotation == 270)
        {
            contentByte.AddTemplate(page, 0, -1f, 1f, 0, 0, pdfReader.GetPageSizeWithRotation(currentPageNumber).Height);
        }
        else
        {
            contentByte.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
        }
    }
}
}
finally
{
    //close the document
    if (document != null && document.IsOpen())
    {
        document.Close();
        document = null;
        foreach (var p in pdfReaders)
        {
            p.Close();
        }
        pdfWriter.Close();
    }
}

As suggested, I have updated the code using PdfCopy, but still I am missing a few requests when I send 8 requests in parallel for a total of 2000 requests, with the same error:

UPDATED CODE USING PDFCOPY:

Document document = null;
PdfReader reader = null;
PdfCopy pdfCopy = null;
PdfImportedPage importedPage = null;

try
{

    using (document = new Document())
    {
        if (metadata != null)
        {
            AddMetadata(document, metadata);
        }
        using (pdfCopy = new PdfCopy(document, new FileStream(destinationFilePath, FileMode.Create)))
        {
            document.Open();
            foreach (var file in sourceFiles)
            {
                using (reader = new PdfReader(file))
                {
                    for (int pageNumber = 1; pageNumber <= reader.NumberOfPages; pageNumber++)
                    {
                        document.SetPageSize(reader.GetPageSizeWithRotation(pageNumber));
                        importedPage = pdfCopy.GetImportedPage(reader, pageNumber);
                        pdfCopy.AddPage(importedPage);
                    }
                }
            }
        }
    }
}
catch (Exception ex)
{
    throw ex;
}

Solution

  • When we put load on the application with 8 requests in parallel, it didn't work because the logic to generate the Merged PDF file name was based on appending the following expression to a fixed string literal:

    DateTime.Now.ToString("yyyyMMdd_hhmmss_fffffff")
    

    and this was generating duplicate file names when under load, and therefore it was appearing that the file is stuck in the process. Using Guid.NewGuid() in place of above solved the problem.

    This was not at all a case of objects not being properly disposed off or any other iTextSharp issue.