如何解决Graphics.DrawString()
我有一个 Windows 窗体,上面有一些数字(此时只有一个数字)并定期刷新它们(数字是随机生成的)。更新过程与应用程序在一个单独的线程中进行,因此表单可以接收用户单击按钮、调整窗口大小等事件。 主要方法:
class Program {
static void Main(string[] args) {
Form o = new Overlay();
Application.Run(o);
}
}
表单类:
public partial class Overlay : Form {
Graphics g;
Drawer drawer;
public Overlay() {
InitializeComponent();
TopMost = true;
TransparencyKey = Color.Black;
BackColor = TransparencyKey;
CheckForIllegalCrossThreadCalls = false;
g = CreateGraphics();
drawer = new Drawer();
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
Thread upd = new Thread(mainLoop);
upd.Start();
}
void mainLoop() {
while (true) {
NetCoreEx.Geometry.Rectangle r;
GetWindowRect(Handle,out r);
Refresh();
drawer.Update(g,new Rectangle(r.Left,r.Top,r.Width,r.Height));
}
}
抽屉:
class Drawer {
Font font;
public Drawer() {
string workingDir = Environment.CurrentDirectory;
string projDir = Directory.GetParent(workingDir).Parent.FullName;
PrivateFontCollection collection = new PrivateFontCollection();
collection.AddFontFile(projDir + "\\Resources\\Athelas-Regular.ttf");
FontFamily fontFamily = new FontFamily("Athelas",collection);
font = new Font(fontFamily,16);
}
public void Update(Graphics g,Rectangle rect) {
string stats = new Random().NextDouble().ToString();
g.DrawString(stats,font,Brushes.Aqua,rect.Width / 2,(int)(rect.Height * 0.75));
}
}
代码对我来说看起来很简单,但是由于某种原因,在正常运行 5-10 秒后,应用程序突然崩溃,并在 DrawString 方法上出现 System.AccessViolateException... 堆栈跟踪
at System.Drawing.SafeNativeMethods.Gdip.GdipDrawString(HandleRef graphics,String textString,Int32 length,HandleRef font,GPRECTF& layoutRect,HandleRef stringFormat,HandleRef brush)
at System.Drawing.Graphics.DrawString(String s,Font font,Brush brush,RectangleF layoutRectangle,StringFormat format)
at System.Drawing.Graphics.DrawString(String s,Single x,Single y)
at OverlayStatistics.Scripts.Drawer.Update(Graphics g,Rectangle rect) in C:\Users\Гриша\source\repos\OverlayStatistics\Scripts\Drawer.cs:line 30
at OverlayStatistics.Overlay.mainLoop() in C:\Users\Гриша\source\repos\OverlayStatistics\Scripts\Overlay.cs:line 50
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state)
at System.Threading.ThreadHelper.ThreadStart()
我花了很多时间调试,但仍然不知道我做错了什么,有什么帮助吗?
解决方法
发生的情况是 FontFamily
实例被释放并导致内部 GDI 调用崩溃。您可以像这样加速行为:
public void Update(Graphics g,Rectangle rect)
{
string stats = new Random().NextDouble().ToString();
g.DrawString(stats,font,Brushes.Aqua,rect.Width / 2,(int)(rect.Height * 0.75));
GC.Collect(); // a good way to check for dispose issues
}
有多种方法可以修复它,例如只需确保 FontFamily
实例也是 Drawer
的成员,即:
class Drawer {
Font font;
FontFamily fontFamily;
public Drawer() {
...
fontFamily = new FontFamily("Athelas",collection);
font = new Font(fontFamily,16);
}
public void Update(Graphics g,Rectangle rect) {
string stats = new Random().NextDouble().ToString();
g.DrawString(stats,(int)(rect.Height * 0.75));
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。