.net PrivateFontCollection.AddMemoryFont在Windows Server 2012 R2上产生随机错误

.net PrivateFontCollection.AddMemoryFont在Windows Server 2012 R2上产生随机错误,.net,fonts,gdi+,windows-server-2012-r2,privatefontcollection,.net,Fonts,Gdi+,Windows Server 2012 R2,Privatefontcollection,我有一个.NET 3.5应用程序,它使用PrivateFontCollection.AddMemoryFont将字体加载到内存中,并使用这些字体生成图像。我最近在Windows Server 2012 R2上安装了此软件,它会产生间歇性错误 此方法说明了该问题: private Bitmap getImage(byte[] fontFile) { using (PrivateFontCollection fontCollection = new PrivateFontCollection

我有一个.NET 3.5应用程序,它使用PrivateFontCollection.AddMemoryFont将字体加载到内存中,并使用这些字体生成图像。我最近在Windows Server 2012 R2上安装了此软件,它会产生间歇性错误

此方法说明了该问题:

private Bitmap getImage(byte[] fontFile)
{
    using (PrivateFontCollection fontCollection = new PrivateFontCollection())
    {
        IntPtr fontBuffer = Marshal.AllocCoTaskMem(fontFile.Length);
        Marshal.Copy(fontFile, 0, fontBuffer, fontFile.Length);
        fontCollection.AddMemoryFont(fontBuffer, fontFile.Length);

        Bitmap image = new Bitmap(200, 50);
        using (Font font = new Font(fontCollection.Families[0], 11f, FontStyle.Regular))
        {
            using (Graphics graphics = Graphics.FromImage(image))
            {
                graphics.DrawString(String.Format("{0:HH:mm:ss}", DateTime.Now), font, Brushes.White, new PointF(0f, 0f));
            }
        }
        return image;
    }
}
在Windows7上,这一点始终有效。在Windows Server 2012 R2上,如果使用多个字体重复调用,则会失败。例如:

getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Arial.ttf"));
即使调用数百次也能正常工作,但调用时使用多种字体:

getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Wingding.ttf"));
getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Arial.ttf"));
将适用于前几个调用(20个左右),但随后将开始产生随机结果(第二个调用有时会返回带有wingdings文本的图像-即混合字体)

我也偶尔(很少)在DrawString调用中得到“GDI+中发生的一般错误”

这些错误都不会在Windows 7上发生

我尝试了各种方法来清理,但没有成功

作为一种解决方法,我尝试将字体文件写入磁盘,然后使用AddFontFile加载,但是(在Windows 2012 R2上)字体文件在整个过程中被锁定,因此无法删除。这使得这一选择无法接受


如果您能帮助AddMemoryFont持续工作,或者帮助AddFontFile解锁文件,我们将不胜感激。

迟来的回答,但可能其他人会对此感到满意: 我遇到了完全相同的问题,经过数小时的反复试验,我发现一个可行的解决方案是将字体(bytearray从数据库中)保存到本地文件,并使用addFontFile方法加载该文件

所有的问题都解决了。这不是一个理想的解决方案,而是一个有效的解决方案

var path = Path.Combine(TemporaryFontPath, customFont.FontFileName);
if (!Directory.Exists(Path.GetDirectoryName(path)))
    Directory.CreateDirectory(Path.GetDirectoryName(path));
if(!File.Exists(path))
    File.WriteAllBytes(path, customFont.FontBytes);

using (var pvc = new PrivateFontCollection())
{
    pvc.AddFontFile(path);
    return pvc.Families.FirstOrDefault();
}

标准GDI+lossage,处理字体实际上不会破坏它。它被放回缓存中,并假设它将再次被使用。一个重要的性能优化,创建字体是相当昂贵的。这对于私有字体来说效果很差,当你破坏它们的家时,字体将使用释放的内存。产生令人困惑的结果,包括硬崩溃。你需要保留收藏以及IntPtr。你找到解决方法了吗?我在Windows Server 2012R2上也有同样的问题。该代码在Windows Server 2003上运行良好。@HansPassant我遇到过一个测试套件,其中即使不处理任何字体或字体系列,GDI+在调用AddMemoryFont()时也会将错误的字体系列添加到集合中。