减少页面错误
使用原生 GDI 将减少页面错误。
引言
我的应用程序出现大量的页面错误。根据我在线上找到的信息,这不太可能导致任何问题,但这引起了我的兴趣去调查:是什么导致了大量的页面错误,以及是否有办法减少它。
背景
几年前,我试图让我的12岁的儿子对编程感兴趣(抱歉,甚至保留了原始名称MyFirstGame
)。因此,我们设计了一个简单的游戏。
请注意:这篇文章不是关于这个游戏 - 我只是用这个游戏来调查页面错误的数量。在玩游戏时,使用标准的.NET图形对象,你会得到大约25000个页面错误/秒。
Using the Code
代码有一个简单的棋盘(5行,4列)。正方形随机放置在每一行,玩家应该点击黑色正方形使其消失。如果你没有点击它,并且它到达底部,你就输了,如果你点击了白色正方形,你就输了。棋盘在Form1
对象内的“Draw
”方法中使用标准.NET绘制。
当你点击“使用GDI”时,会使用gdi32.dll - 在Draw2
方法中。你会看到页面错误急剧减少。
(为了更容易观察,我每秒在屏幕上显示页面错误,无需打开任务管理器。)
此外,使用GDI绘制的平均速度大约快10倍。
Draw
方法如下所示
private void Draw(Graphics g)
{
if (checkBoxUseGDI.Checked)
{
Draw2(g);
return;
}
graphics.Clear(Color.White);
int left = 0;
int top = board.Top;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
{
Rectangle rect = new Rectangle(left, top, 100, 150);
if (board.Cells[i, j] > -1)
{
graphics.FillRectangle(Brushes.Black, rect);
}
graphics.DrawRectangle(Pens.Black, rect);
left += 100;
}
top += 150;
left = 0;
}
g.DrawImage(bitmap, 0, 0);
}
Draw2
方法如下所示
private void Draw2(Graphics g)
{
IntPtr hdc2 = g.GetHdc();
IntPtr hdc = GDI.CreateCompatibleDC(hdc2);
IntPtr hBitmap = GDI.CreateCompatibleBitmap(hdc, 401, 601);
GDI.SelectObject(hdc, hBitmap);
IntPtr brushWhite = GDI.CreateSolidBrush(0xFFFFFF);
GDI.FillRgn(hdc, GDI.CreateRectRgn(0, 0, 401, 601), brushWhite);
GDI.DeleteObject(brushWhite);
IntPtr brushBlack = GDI.CreateSolidBrush(0x0);
int left = 0;
int top = board.Top;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
{
GDI.Rectangle(hdc, left, top, left + 101, top + 151);
if (board.Cells[i, j] > -1)
{
GDI.FillRgn(hdc, GDI.CreateRectRgn(left, top, left + 101, top + 151), brushBlack);
}
left += 100;
}
top += 150;
left = 0;
}
GDI.DeleteObject(brushBlack);
GDI.BitBlt(hdc2, 0, 0, 401, 601, hdc, 0, 0, GDI.TernaryRasterOperations.SRCCOPY);
g.ReleaseHdc(hdc2);
GDI.DeleteDC(hdc);
GDI.DeleteObject(hBitmap);
}
关注点
我发现这个网站很有帮助:http://pinvoke.net/default.aspx
历史
- 2018年12月26日:初始版本