GDI+ Leak when printing on some printers

Viewed 122

This is an example of a GDI handle leak when printing on some printers on Windows 10 Pro (20H2 - 19042.868). All printers have official drivers installed.

For example if I try this on one printer, lets say Printer A everything is fine and handles are getting disposed. GDI Handles go to 70 max and then drop to ~30 - no leak, when I run the exact same code but on Printer B GDI handles leak quickly to 10000 (max for a process), around 5000 BitMaps (observed with task manager and GDIView) and I get exception "A generic error occurred in GDI+."

Stack trace is:

   at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
   at System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)
   at System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, PointF point)
   at DrawStringTests.SimplePrinter.printerDoc_PrintPage(Object sender, PrintPageEventArgs e) in c:\projects\TESTS\DrawStringTests\SimplePrinter.cs:line 38

.

//If there is a leak this will generate exception
for (int i = 0; i < 100; i++)
{
    using (var simplePrinter = new SimplePrinter())
    {
        simplePrinter.Print("POSPRINTER");
    }
}


class SimplePrinter : IDisposable
{
    Font _font;
    Brush _brush;
    PrintDocument printerDoc;

    public SimplePrinter()
    {
        _font = new Font("Consolas", 12);
        _brush = new SolidBrush(Color.Black);
    }

    public void Print(string printerName)
    {
        printerDoc = new PrintDocument();
        printerDoc.PrintPage += printerDoc_PrintPage;
        printerDoc.PrinterSettings.PrinterName = printerName;
        printerDoc.Print();
    }

    void printerDoc_PrintPage(object sender, PrintPageEventArgs e)
    {
        int y = 0;
        for (int i = 0; i < 100; i++)
        {
            e.Graphics.DrawString("qwertzuiopšđasdfghjklčćžyxcvbnm", _font, _brush, new PointF(0, y));
            y += (_font.Height + 1);
        }
        e.HasMorePages = false;
    }

    public void Dispose()
    {
        _font.Dispose();
        _brush.Dispose();
        printerDoc.PrintPage -= printerDoc_PrintPage;
        printerDoc.Dispose();
    }
}

Why is this happening only for some printers and not all of them? What am I doing wrong?

0 Answers
Related