我在c#中试验cgi。我做了一个应用程序,你可以在一个可以调整大小的矩形内移动一个正方形(带箭头)。我正在绘制一个矩形,以调整它的大小。我使用碰撞类限制移动经过边缘。
一切似乎都很好,但我担心它的内存使用情况。当我开始增加它的大小时,内存消耗会上升并触发GC。
有人可以帮我找到这个漏洞吗?我做错了什么会增加使用量?我是否以错误的方式使用缓冲区?
编辑::实际上,我发现导致内存使用的是这行代码。在注释掉这段代码之后,我的程序只使用了16MB而不是2GB。
if (player.rectHeight >= tempWidth)
{
Program.bufferedGraphics = context.Allocate(Program.graphics,
new Rectangle(0, 0, Convert.ToInt32(player.rectWidth) + 100,
Convert.ToInt32(player.rectHeight) + 100));
}
感谢您的时间。
代码
class Program
{
static Graphics graphics;
static BufferedGraphics bufferedGraphics;
static Player player;
static Collision collision;
static Utility utility;
static SByte value = 0;
static float tempWidth = 500;
static void Main()
{
Program.player = new Player();
Program.utility = new Utility();
Program.collision = new Collision();
Console.CursorVisible = false;
Process process = Process.GetCurrentProcess();
Program.graphics = Graphics.FromHdc(GetDC(process.MainWindowHandle));
BufferedGraphicsContext context = BufferedGraphicsManager.Current;
context.MaximumBuffer = new Size(Console.WindowWidth, Console.WindowHeight);
Program.bufferedGraphics = context.Allocate(Program.graphics, new Rectangle(0, 0, Convert.ToInt32(player.rectWidth),
Convert.ToInt32(player.rectHeight)));
while (true)
{
collision.worldEdges = new Collision.WorldEdges()
{
rightBorder = Convert.ToInt32(player.rectWidth),
leftBorder = 0,
topBorder = 0,
bottomBorder = Convert.ToInt32(player.rectHeight),
};
if (player.rectHeight >= tempWidth)
{
Program.bufferedGraphics = context.Allocate(Program.graphics, new Rectangle(0, 0, Convert.ToInt32(player.rectWidth) + 100,
Convert.ToInt32(player.rectHeight) + 100));
}
//Debug.Print(Convert.ToString(player.rectHeight));
// Debug.Print(Convert.ToString(player.x));
//Debug.Print(Convert.ToString(player.x- collision.worldEdges.rightBorder));
if (player.y > collision.worldEdges.bottomBorder-19.7f) // if on the edge, clamp its movement
{
player.y = collision.worldEdges.bottomBorder-19.8f;
}
if (player.x > collision.worldEdges.rightBorder - 19.7)
{
player.x = collision.worldEdges.rightBorder - 19.8f;
}
else
{
Program.player.DoMove();
}
Program.player.ResizeScreen(out value); //check whether resize the rectangle
if (value ==1) //g decrease size
{
bufferedGraphics.Graphics.FillRectangle(Brushes.Black, 0, 0,
Convert.ToInt32(player.rectWidth), Convert.ToInt32(player.rectHeight));
player.rectHeight -= 0.08f;
player.rectWidth -= 0.08f;
tempWidth = player.rectWidth;
}
if (value == -1) //h increase size
{
bufferedGraphics.Graphics.FillRectangle(Brushes.Black, 0, 0,
Convert.ToInt32(player.rectWidth), Convert.ToInt32(player.rectHeight));
player.rectHeight += 0.08f;
player.rectWidth += 0.08f;
//Program.bufferedGraphics = context.Allocate(Program.graphics, new Rectangle(0, 0, 320,200));
bufferedGraphics.Graphics.FillRectangle(Brushes.Green, 0, 0, Convert.ToInt32(player.rectWidth),
Convert.ToInt32(player.rectHeight));
tempWidth = player.rectWidth;
}
else
{
bufferedGraphics.Graphics.FillRectangle(Brushes.Green, 0, 0, Convert.ToInt32(player.rectWidth),
Convert.ToInt32(player.rectHeight));
}
Program.player.DrawPlayer(Program.bufferedGraphics.Graphics, Brushes.Blue); //draw player controlled cube
Program.bufferedGraphics.Render(Program.graphics); //finally render on screen
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern short GetKeyState(int nVirtKey);
}
class Player //detect input and set player size and it's movement
{
const int LEFT = 0x25;
const int UP = 0x26;
const int RIGHT = 0x27;
const int DOWN = 0x28;
const int G = 0x47;
public float rectWidth = 200, rectHeight = 200;
public float x;
public float y;
public Player()
{
this.x = 0;
this.y = 0;
}
public void DoMove()
{
if ((GetKeyState(LEFT) | 0x8000) > 0 && this.x < rectWidth-10)
{
this.x += 0.1f;
}
if ((GetKeyState(RIGHT) | 0x8000) > 0 && this.x > 0)
{
this.x -= 0.1f;
}
if ((GetKeyState(UP) | 0x8000) > 0 )
{
this.y += 0.1f;
}
if ((GetKeyState(DOWN) | 0x8000) > 0 && this.y > 0)
{
this.y -= 0.1f;
}
}
public void DrawPlayer(Graphics g, Brush color)
{
g.FillRectangle(color, this.x , this.y , 20, 20);
}
public void ResizeScreen(out SByte value)
{
if ((GetKeyState(G) | 0x8000) < 0)
{
value = 1;
}
else if ((GetKeyState(0x48) | 0x8000) < 0)
{
value = -1;
}
else
{
value = 0;
}
}
[DllImport("user32.dll")]
static extern short GetKeyState(int nVirtKey);
}
class Collision //used for colliding with other objects and world boundaries
{
public struct WorldEdges
{
public int leftBorder;
public int rightBorder;
public int topBorder;
public int bottomBorder;
}
public WorldEdges worldEdges;
}
答案 0 :(得分:0)
毫不奇怪,内存消耗增加,GC也参与其中。你有一个无限循环,不断分配一个大缓冲区(你的bufferedGraphics
),使用它,然后让它挂起。你不仅疯狂地消耗记忆,而且还没有丢弃一次性物品。
BufferedGraphics
类实现IDisposable interface,这意味着当您使用它时,您应该调用Dispose
方法。这样做很可能会减轻很多记忆压力。它不会消除记忆压力,但应该稍微缓解一下。
您可能还想研究一次分配bufferedGraphics
个对象并重新使用它的可能性。我对BufferedGraphics
不够熟悉,所以我不能说这是否合理。但是如果你能做到这一点,那么减少GC对你的程序的影响应该有很长的路要走。
最后,你真的需要这个在while (true)
循环中全速运行吗?如果您可以在计时器上执行此操作,例如每20或50毫秒一次,则可以减少CPU和内存的负载。