GDI打印在C#内存泄漏问题,原因不明的错误,无法线程

时间:2013-04-10 20:41:19

标签: c# multithreading printing memory-leaks gdi

我们正在使用对GDI Printing API的Win32调用来打印图形。

我注意到在某些PCL打印队列中,我们在打印时会泄漏GDI内存。据我所知,一切都正在妥善处理。不是我公司的管理员,我很难分辨哪些驱动程序打印队列正在使用。 PCL6司机似乎是罪魁祸首。我见过的其他看似无关的问题:

  

System.ComponentModel.Win32Exception:传递给系统调用的数据区域太小   System.ComponentModel.Win32Exception:操作成功完成

var hdc = GdiPrintWin32.CreateDC(IntPtr.Zero, printerName, IntPtr.Zero, IntPtr.Zero);
if (hdc == IntPtr.Zero)
    throw GetError("Device context failed for {0}", printerName);

try
{
    if (GdiPrintWin32.StartDoc(hdc, ref doc) <= 0)
        throw GetError("Failed to start print job");

此逻辑目前正在Windows服务中托管的WCF中完成。当我将实例模式设置为单一并锤击它时,我只得到它的前几次调用;当我将实例模式设置为每次调用时,重现起来要容易得多。

我也看到了错误,基本上没有呼叫可以通过该服务大约20分钟,并需要重新启动来修复。我注意到在停止服务后,Windows事件日志会产生以下效果:

  

从\ Registry \ User ...泄漏的2个用户注册表句柄:进程3792(\ Device \ HarddiskVolume1 \ Windows \ System32 \ rundll32.exe)已打开键\ REGISTRY \ USER ...进程3792(\ Device \ HarddiskVolume1 \ Windows \ System32 \ rundll32.exe)已打开密钥... \ Software \ Hewlett-Packard \ HP SSNP

基本上它对我们来说只是一场噩梦。有没有人有这样的经历?

我们用来打印的代码的内容是:

var doc = new Docinfo { DocName = printJobName };

// create a device-context 
var hdc = GdiPrintWin32.CreateDC(IntPtr.Zero, printerName, IntPtr.Zero, IntPtr.Zero);
if (hdc == IntPtr.Zero)
    throw GetError("Device context failed for {0}", printerName);

try
{
    if (GdiPrintWin32.StartDoc(hdc, ref doc) <= 0)
        throw GetError("Failed to start print job");


    foreach (PrintingMetafile metafile in pages)
    {
        var bytes = metafile.GetBytes();

        // load the bytes to a memory location and get the pointer
        var inMemRef = GdiPrintWin32.SetEnhMetaFileBits((uint)bytes.Length, bytes);

        if (inMemRef == IntPtr.Zero)
            throw GetError("Failed to create EMF in memory");

        // Get the pixel coordinates of the paper
        var x = 0; // GdiPrintWin32.GetDeviceCaps(hdc, HORZSIZE);
        var y = 0; // GdiPrintWin32.GetDeviceCaps(hdc, VERTSIZE);
        var hres = GdiPrintWin32.GetDeviceCaps(hdc, HORZRES);
        var vres = GdiPrintWin32.GetDeviceCaps(hdc, VERTRES);

        var rect = new Rect { Left = x, Top = y, Right = hres, Bottom = vres };

        if (GdiPrintWin32.StartPage(hdc) <= 0)
            throw GetError("StartPage failed");


        if (GdiPrintWin32.PlayEnhMetaFile(hdc, inMemRef, ref rect) == 0)
            throw GetError("PlayEnhMetaFile failed");

        if (GdiPrintWin32.EndPage(hdc) <= 0)
            throw GetError("EndPage failed");


        if (inMemRef != IntPtr.Zero)
        {
            GdiPrintWin32.DeleteEnhMetaFile(inMemRef);
        }
    }

    if (GdiPrintWin32.EndDoc(hdc) <= 0)
        throw GetError("Failed to finish print job");
}
finally
{
    GdiPrintWin32.DeleteDC(hdc);
}

0 个答案:

没有答案