Solution for a memory consumption problem when printing many PDFs (VB.NET)

Q: I've built a process that iterates through all the pdf files in a
folder and sends them to the default printer. Each time it prints a
file, it takes some more memory and never releases it. Because each job
contains 100+ files, the memory used quickly exceeds that of the client
machine and ultimately crashes the application, etc...

I've isolated the line where the memory jump happens.
I've tried several different ways of destroying objects, but none
seem to get the memory back.

The code is a follows:

Imports System.IO

Imports System
Imports System.Drawing
Imports System.Drawing.Printing

Imports pdftron
Imports pdftron.PDF
Imports pdftron.Common
Imports pdftron.Filters

Public Class frmPrint

    Private pdfdoc As PDFDoc = Nothing
    Private pdfdraw As PDFDraw = Nothing
    Private pageitr As PageIterator = Nothing

    Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnBrowse.Click
        FolderBrowserDialog1.ShowDialog()
        txtFolder.Text = FolderBrowserDialog1.SelectedPath
    End Sub

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnPrint.Click
        Dim myFiles() As FileInfo
        Dim oPDFTargetFolder As DirectoryInfo
        Dim myTimer As Date

        If Trim(txtFolder.Text) = "" Then
            MessageBox.Show("Folder not specified.", "Invalid Folder",
MessageBoxButtons.OK, MessageBoxIcon.Warning)
        Else
            oPDFTargetFolder = New DirectoryInfo(txtFolder.Text)
            If Not oPDFTargetFolder.Exists Then
                MessageBox.Show("Folder does not exist.", "Invalid
Folder", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            Else
                myFiles = oPDFTargetFolder.GetFiles("*.PDF")
                If myFiles.GetLength(0) <= 0 Then
                    MessageBox.Show("No PDF files to print.", "No
Files", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Else
                    Me.Cursor = Cursors.WaitCursor
                    Array.Sort(myFiles, New CompareFileInfo)

                    For Each oFileInfo As FileInfo In myFiles

                        PDFPrint(txtFolder.Text, oFileInfo.Name)

                        'Just a timer to keep the printer queue under
control.
                        myTimer = Now
                              Do While
(Now.Subtract(myTimer).TotalSeconds < 6)
                        Loop

                    Next
                    'MessageBox.Show("Printing Complete.", "Printing
Complete", MessageBoxButtons.OK)
                    Me.Cursor = Cursors.Default
                End If
            End If
        End If

    End Sub

    Private Sub PDFPrint(ByVal strFolder As String, ByVal strFile As
String)
        Dim pdPrinter As PrintDocument = New PrintDocument

        PDFNet.Initialize()
        Try
            Console.WriteLine("Opening the input file...")
            pdfdoc = New PDFDoc(strFolder & "\" & strFile)
            pdfdoc.InitSecurityHandler()
            pageitr = pdfdoc.PageBegin

            pdfdraw = New PDFDraw
            pdfdraw.SetRasterizerType(PDFRasterizer.Type.e_BuiltIn)

            AddHandler pdPrinter.PrintPage, AddressOf PrintPage
            pdPrinter.Print()
            pdfdoc.Close()
        Catch e As PDFNetException
            Console.WriteLine(e.Message)
        End Try
        PDFNet.Terminate()
    End Sub

    Private Sub PrintPage(ByVal sender As Object, ByVal ev As
PrintPageEventArgs)
        Dim gr As Graphics = ev.Graphics
        gr.PageUnit = GraphicsUnit.Inch
        Dim rectPage As Rectangle = ev.PageBounds

        Dim dpi As Single = gr.DpiX
        If dpi > 300 Then dpi = 300
        pdfdraw.SetDPI(dpi)

        Dim left As Double = (rectPage.Left -
ev.PageSettings.HardMarginX) / 100
        Dim right As Double = (rectPage.Right -
ev.PageSettings.HardMarginX) / 100
        Dim top As Double = (rectPage.Top -
ev.PageSettings.HardMarginY) / 100
        Dim bottom As Double = (rectPage.Bottom -
ev.PageSettings.HardMarginY) / 100
        Dim rect As PDFTRON.PDF.Rect = New Rect(left * 72, bottom * 72,
right * 72, top * 72)

        Try

'***********************************************************************
            'This line causes the memory usage that never gets
released...!!
            pdfdraw.DrawInRect(pageitr.Current, gr, rect)

'***********************************************************************
        Catch ex As Exception
            Console.WriteLine("Printing Error: " + ex.ToString)
        End Try

        pageitr.Next()

        ev.HasMorePages = Not (pageitr = pdfdoc.PageEnd)
    End Sub

End Class
---
A:

Since you are repeatedly re-creating PDFDraw objects you should call
pdfdraw.Close() just before pdfdoc.Close() in your PDFPrint method.
Otherwise pdfdraw objects may keep on accumulating because .NET garbage
collector is sometimes not very smart.

Another option is to allocate PDFDraw only one time and to keep on
reusing it to print/render all PDF documents.

Q:

I can't use your suggestion to use pdfdraw.Close() because there isn't
any 'Close' function for PDFDraw.

I took your suggestion to only use the PDFDraw object once.

Instead of using...
pdfdraw = New PDFDraw
I've changed it to read...
If pdfdraw Is Nothing Then
     pdfdraw = New PDFDraw
End If

This works, but still holds the last page in memory and won't let it
go until the application quits.)
------------
A:

You are right, there is no Close() method is PDFDraw. The method you
should use is pdfdraw.Dispose(). Calling dispose between print calls
to different documents will free all allocated memory.