2017-10-25 7 views
-1

私はc#でCGIを試しています。私はサイズ変更可能な四角形の内側に四角形(矢印付き)を動かすことができるアプリケーションを作った。私はそれをサイズ変更するために1つ以上の四角形を描いています。私は衝突クラスを使用して、過去のエッジの動きを制限します。あまりにも多くのメモリを使用するC#のコンソールCGIグラフィック

私はメモリの使用について心配していますが、すべてうまく見えます。サイズを増やし始めると、メモリ消費量が上がり、GCがトリガされます。

誰かがこのリークを見つけるのを助けることができますか?私は使い方を悪くする何か間違ったことをしていますか?バッファを間違った方法で使用していますか?

EDIT ::実際に、このコード行がメモリ使用量の原因となっていることがわかりました。このコードブロックをコメントアウトした後、私のプログラムは2GBの代わりに16MBしか使用しませんでした。

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

これは、メモリの消費量が増加し、GCが巻き込まことは驚きではありません。無限のループがあり、大きなバッファ(あなたのbufferedGraphics)が連続的に割り当てられ、それを使用してぶら下がります。あなたは狂気のような記憶を消費しているだけでなく、使い捨ての物を処分できません。

BufferedGraphicsクラスは、IDisposable interfaceを実装しています。つまり、使用したらDisposeメソッドを呼び出すことになっています。そうすることで、かなりのメモリ圧迫を和らげるでしょう。それはメモリの圧力を排除することはありませんが、それを少し緩和する必要があります。

bufferedGraphicsオブジェクトを1回だけ割り当てて再利用する可能性も検討したいと思うかもしれません。私はBufferedGraphicsで十分に身近ではないので、合理的かどうかは言えません。しかし、もしあなたがそれを行うことができれば、あなたのプログラムへのGCの影響を減らすためには長い道のりが必要です。

最後に、while (true)ループでフルスピードで実行するには本当に必要ですか?タイマーでこれを行うことができれば、20ミリ秒または50ミリ秒ごとに1回と言えば、CPUとメモリの負荷を軽減できます。

+0

ご回答いただきありがとうございます。間違いなく私のコードを更新します。 –

+0

私はその漏れの原因を強調するために私の質問を編集しました。 –

関連する問題