使用方法获取嵌入字体导致受保护的内存错误 [英] Using a method to get Embedded Font Causes Protected Memory Error

查看:221
本文介绍了使用方法获取嵌入字体导致受保护的内存错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  ///< summary> 
///返回嵌入字体
///< / summary>
///< param name =ImagePath>字符串以namespace开头,例如MyProgram.Image.png< / param>
///<返回>< /返回>
public static Font GetEmbeddedFont(string FontPath,float Size)
{
Font _font = null;
Thread getFontThread = new Thread(()=> GetFont(FontPath,Size,out _font));
getFontThread.Start();
getFontThread.Join();
return _font;

#region GetFont
private static void GetFont(string FontPath,float Size,out Font FontOut)
{
Font fnt = null;
汇编asm = Assembly.GetExecutingAssembly();
Stream resStream = asm.GetManifestResourceStream(FontPath);
if(null!= resStream)
{
//
// GDI +需要一个指向内存的指针,GDI需要内存。
//我们会让他们都快乐。
//
//首先将字体读入缓冲区
byte [] rgbyt = new Byte [resStream.Length];
resStream.Read(rgbyt,0,rgbyt.Length);
resStream.Close();
//然后做非托管字体(Windows 2000及更高版本)
//原因是GDI +会为
创建一个字体对象,像RichTextBox这样的控件,确保GDI
//稍后识别字体名称。
uint cFonts;
AddFontMemResourceEx(rgbyt,rgbyt.Length,IntPtr.Zero,out cFonts);
//现在做托管字体
IntPtr pbyt = Marshal.AllocCoTaskMem(rgbyt.Length);
if(null!= pbyt)
{
Marshal.Copy(rgbyt,0,pbyt,rgbyt.Length);
m_pfc = new PrivateFontCollection();
m_pfc.AddMemoryFont(pbyt,rgbyt.Length);
Marshal.FreeCoTaskMem(pbyt);



if(m_pfc.Families.Length> 0)
{
// Handy如何使用一个Font构造函数
// FontFamily对象,呵呵? :-)
fnt = new Font(m_pfc.Families [0],Size);
}
m_pfc.Dispose();
FontOut = fnt;



$ b我使用一个线程来尝试等待它完成,因为错误似乎发生,如果这个方法是在很短的时间内多次调用。

我怎么能阻止这个错误发生,我认为这是与方法在对方的快速连续调用中。



我在这里得到异常:

  _font = value; 
using(Graphics g = _parent.CreateGraphics())
{
SizeF soize = g.MeasureString(_text,_font);
_size = new Size((int)soize.Width,(int)soize.Height);
_width = _size.Width;
_height = _size.Height;

在行g.MeasureString(_text,_font);



但是我知道这个错误是在GetEmbeddedFont方法中的,因为如果字体是使用GetEmbeddedFont方法设置的,它只会抛出一个错误。

它会正常工作一次,但是如果在第一次之后第二次使用,它会抛出错误。

如果我调试代码,_font返回:

  {Name ='((System.Drawing.Font)(_ font))。fontFamily.Name '抛出一个'System.ArgumentException'Size = 15.0的异常


解决方案
。这很好,没有访问冲突。

我强烈建议您删除Marshal.FreeCoTaskMem()调用。无论是完全,Windows程序终止时自动清理,或将其移动,例如,FormClosed事件。你的m_pfc.Dispose()调用也是一样的。不要释放资源,直到完成它们。


I am using this code to get an embedded font:

/// <summary>
    /// Returns an Embedded Font
    /// </summary>
    /// <param name="ImagePath">String begins with namespace e.g MyProgram.Image.png</param>
    /// <returns></returns>
    public static Font GetEmbeddedFont(string FontPath, float Size)
    {
        Font _font = null;
        Thread getFontThread = new Thread(() => GetFont(FontPath, Size, out _font));
        getFontThread.Start();
        getFontThread.Join();
        return _font;            
    }
    #region GetFont
    private static void GetFont(string FontPath, float Size, out Font FontOut)
    {
        Font fnt = null;
        Assembly asm = Assembly.GetExecutingAssembly();
        Stream resStream = asm.GetManifestResourceStream(FontPath);
        if (null != resStream)
        {
            // 
            // GDI+ wants a pointer to memory, GDI wants the memory.
            // We will make them both happy.
            //
            // First read the font into a buffer
            byte[] rgbyt = new Byte[resStream.Length];
            resStream.Read(rgbyt, 0, rgbyt.Length);
            resStream.Close();
            // Then do the unmanaged font (Windows 2000 and later)
            // The reason this works is that GDI+ will create a font object for
            // controls like the RichTextBox and this call will make sure that GDI
            // recognizes the font name, later.
            uint cFonts;
            AddFontMemResourceEx(rgbyt, rgbyt.Length, IntPtr.Zero, out cFonts);
            // Now do the managed font
            IntPtr pbyt = Marshal.AllocCoTaskMem(rgbyt.Length);
            if (null != pbyt)
            {
                Marshal.Copy(rgbyt, 0, pbyt, rgbyt.Length);
                m_pfc = new PrivateFontCollection();
                m_pfc.AddMemoryFont(pbyt, rgbyt.Length);
                Marshal.FreeCoTaskMem(pbyt);
            }
        }

        if (m_pfc.Families.Length > 0)
        {
            // Handy how one of the Font constructors takes a
            // FontFamily object, huh? :-)
            fnt = new Font(m_pfc.Families[0], Size);
        }
        m_pfc.Dispose();    
        FontOut = fnt;            
    }

I use a Thread to attempt to wait for it to finish, because the error seems to occur, if this method is called multiple times within a short space of time.

How can I stop this error occuring, I think it has something to do with the method being called within quick succession of each other.

I get the exception here:

_font = value;
            using (Graphics g = _parent.CreateGraphics())
            {
                SizeF soize = g.MeasureString(_text, _font);
                _size = new Size((int)soize.Width, (int)soize.Height);
                _width = _size.Width;
                _height = _size.Height;
            }

On the line g.MeasureString(_text, _font);

However I know that the error is in the GetEmbeddedFont Method, as it only throws an error if the font is set using the GetEmbeddedFont method.

It will work fine once, but if it is used a second time to shortly after the first, it will throw the error.

And if I debug the code, _font returns this:

{Name = '((System.Drawing.Font)(_font)).fontFamily.Name' threw an exception of type 'System.ArgumentException' Size=15.0}

解决方案

There's a documentation problem with AddMemoryFont(), it doesn't specify how long the pointer needs to remain valid. I've always chosen the conservative route and made sure to not release the memory until after the program stops using the private font. That has worked well, no access violations.

I thus strongly recommend you remove the Marshal.FreeCoTaskMem() call. Either entirely, Windows automatically cleans up when the program terminates, or move it to, say, the FormClosed event. The same goes for your m_pfc.Dispose() call. Don't release resources until you're done with them.

这篇关于使用方法获取嵌入字体导致受保护的内存错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆