正如标题已经说明的那样,我遇到了一个AccessViolationException,因为我试图使用BufferedGraphics
对象在.NET中绘制一个Control。这种情况发生在一段时间后,更早或更晚。在评估对象的地址时,我注意到它随着程序的继续而不断增加。
我已经采取了一些措施来保存记忆,这似乎有点帮助,但最终没有解决问题。似乎问题的出现与我是否在函数结束之前处理图形对象无关。
private void checkMemory()
{
long mem = GC.GetTotalMemory(false);
//Console.WriteLine("Allocated memory: " + mem.ToString());
if (mem > criticalMemorySize)
{
Console.WriteLine("GC started");
GC.Collect(1, GCCollectionMode.Forced, true);
}
}
BufferedGraphics graphics;
protected override void OnPaint(PaintEventArgs e)
{
lock (e.Graphics)
{
base.OnPaint(e);
checkMemory();
if (e.ClipRectangle.Width * e.ClipRectangle.Height == 0)
return;
if (graphics == null || graphics.Graphics == null || graphics.Graphics.ClipBounds != e.ClipRectangle)
graphics = _bufferedGraphicsContext.Allocate(e.Graphics, e.ClipRectangle);
PaintBackground(graphics.Graphics);
PaintHeader(graphics.Graphics);
PaintBody(graphics.Graphics);
DrawGrid(graphics.Graphics);
//...
graphics.Render(e.Graphics);
graphics.Graphics.Dispose();
graphics.Dispose();
}
}
调用g.DrawString
:
private void PaintBody(Graphics g)
{
Font seriffont = Design.CreateSerifFont(fontSize);
Point mousePos = PointToClient(MousePosition);
int hfeed = headHeight + headLineWidth - 2; //Dunno
for (int y = 0; y < LineCount; y++)
{
int vfeed = 0;
for (int x = 0; x < ColumnCount; x++)
{
String s = "";
Rectangle area = new Rectangle(vfeed, hfeed, colwidth, cellHeight);
switch (_tableData[y][x])
{
case ExBool.DontCare:
s = "*";
break;
case ExBool.False:
s = "0";
break;
case ExBool.True:
s = "1";
break;
default:
s = " ";
break;
}
Color backColor = cellBackColor;
if (_activeHeaderColumn == x)
{
backColor = cellActiveColColor;
}
if (area.Contains(mousePos))
{
backColor = cellHoverColor;
}
if (area.Contains(mousePos) &&
((MouseButtons & MouseButtons.Left) == MouseButtons.Left))
{
backColor = cellActiveColor;
}
g.FillRectangle(new SolidBrush(backColor), area);
g.DrawString(s, seriffont, Brushes.Black, area,
new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
if (x != InputValues.Count() - 1)
{
vfeed += lineWidth + colwidth;
}
else
{
vfeed += typeSepLineWidth + colwidth;
}
}
hfeed += cellHeight + lineWidth;
}
}
这是我得到的例外:
System.AccessViolationException was unhandled
HResult = -2147467261
Message=Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben.Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
Source= System.Drawing
StackTrace:
bei System.Drawing.SafeNativeMethods.Gdip.GdipDrawString(HandleRef graphics, String textString, Int32 length, HandleRef font, GPRECTF& layoutRect, HandleRef stringFormat, HandleRef brush)
bei System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)
bei KarnaughVeitch.Controls.TruthTableControl.PaintBody(Graphics g)
bei KarnaughVeitch.Controls.TruthTableControl.OnPaint(PaintEventArgs e)
bei KarnaughVeitch.Controls.TruthTableControl.TruthTableControl_MouseMove(Object sender, MouseEventArgs e)
bei System.Windows.Forms.Control.OnMouseMove(MouseEventArgs e)
bei System.Windows.Forms.Control.WmMouseMove(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.Run(Form mainForm)
bei KarnaughVeitch.Program.Main()
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
InnerException:
有谁知道如何解决这个问题? 提前谢谢!
Context变量是全局创建的,如下所示:
BufferedGraphicsContext _bufferedGraphicsContext = new BufferedGraphicsContext()
在您经常使用BufferedGraphics
的案例的文档中建议这样做。
这些函数是自定义控件的一部分,允许用户输入二进制函数输入和输出。由于我不知道任何类似的控制,我只是自己写了一个。
每次需要重新绘制Control时调用上述函数,例如,如果用户移动鼠标,点击某些内容等等,所有这些操作都需要视觉反馈。
通常,它可以按照需要工作,除了在使用Control很长一段时间后发生的异常......
由于异常几乎只发生在DrawString
函数上,因此NullReference(根据HResult,如果我没有记错)不是由于绘图过程本身,而是由于其中一个论点还是什么?
答案 0 :(得分:0)
那可能不完全是您的情况(而且我相信两年半以后,这对您来说已经不现实了),但是仍然如此。
您的代码中包含以下行:
error
它看起来像是您自己的代码,因为我在Google中找不到任何提及。因此,此方法的实现可能会导致您观察到错误:
tsem
我会说,这是Font seriffont = Design.CreateSerifFont(fontSize);
的不良设计-它可以在static class Design {
static Font CreateSerifFont() {
var fonts = new PrivateFontCollection();
fonts.AddFontFile(@"c:\some_font.ttf");
return new Font(fonts.Families[0], 12);
}
}
的使用状态下进行处理,这会导致AccessViolationException。可以通过将PrivateFontCollection
从本地作用域移到类字段来修复上述代码,如下所示:
Font