1

I have this code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SharpDX.XInput;
using System.Threading;
using System.Reflection;
using System.Diagnostics;

namespace ControllerCheck
{
    public partial class CheckForm : Form
    {
        public CheckForm()
        {
            InitializeComponent();
        }

        Graphics x;

        private TimeSpan Redraw(object sender, EventArgs e)
        {
            var watch = Stopwatch.StartNew();
            Bitmap b = new Bitmap(DisplayPanel.Width, DisplayPanel.Height);
            Graphics g = Graphics.FromImage(b);
            g.FillRectangle(Brushes.White, 0, 0, DisplayPanel.Width, DisplayPanel.Height);
            g.FillRectangle(Brushes.Black, 0, 0, DisplayPanel.Width, DisplayPanel.Height);

            x.DrawImageUnscaled(b, 0, 0);
            watch.Stop();
            return watch.Elapsed;
        }

        private async void CheckForm_Shown(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                x = DisplayPanel.CreateGraphics();

                while (true)
                {
                    var ts = Redraw(null, null);
                    Console.WriteLine("Zajęło to {0} ticków, czyli {1} ms", ts.Ticks, ts.TotalMilliseconds); //(It tooked {0} ticks or {1} ms)
                }
            });
        }


    }
}

I want to make small program to check XInput with SharpDX

But RAM usage goes to 2 GB and throws OutOfMemoryException on "x.DrawImageUnscaled(b, 0, 0)" in Redraw (Look at screenshot)

I draw white and black rectangles to see if it's working, and it is, I see only black rectangle so RAM is the only problem

RAM usage goes to 2 GB and crashes on "<code>x.DrawImageUnscaled(b, 0, 0)</code>" - OutOfMemoryException

TheChilliPL
  • 337
  • 1
  • 5
  • 14

1 Answers1

2

You need to dispose your Bitmap and Graphics with a using statement:

using (var b = new Bitmap(DisplayPanel.Width, DisplayPanel.Height))
using (var g = Graphics.FromImage(b))
{
    g.FillRectangle(Brushes.White, 0, 0, DisplayPanel.Width, DisplayPanel.Height);
    g.FillRectangle(Brushes.Black, 0, 0, DisplayPanel.Width, DisplayPanel.Height);

    x.DrawImageUnscaled(b, 0, 0);
}

Since much of the memory held by a Bitmap is unmanaged you cannot count on the GC to clean it up for you in a timely fashion once it becomes unreferenced. It will eventually, just not as soon as it would if only managed memory was being consumed.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • By the way, shouldn't it dispose itself on function (Redraw) end? – TheChilliPL Sep 26 '16 at 06:14
  • Eventually the GC will kick in and clean up unreferenced managed objects - but because the memory of `Bitmap` is mostly unmanaged, the apparent memory pressure may not reflect the actual memory consumed. Also, since the unmanaged memory eventually gets cleaned up on the [finalizer thread](https://stackoverflow.com/questions/5223325/garbage-collection-and-finalizers-finer-points) it doesn't happen right away. – dbc Sep 26 '16 at 06:16
  • Even if `Dispose` is not called explicitly, why would finalization not automatically do the clean up, which would also release the un-managed objects as it collects the managed objects holding them. Here calling `Dispose` is a good practice, but reason to fail @ 2 GB is probably due system / memory limitation – Mrinal Kamboj Sep 26 '16 at 06:52
  • @MrinalKamboj - it will do so eventually. But OP is allocating bitmaps in a tight loop, so it's quite possible to run out of memory or system resources before the finalizer thread does its job. Calling `Dispose()` deterministically inside the loop prevents that. – dbc Sep 26 '16 at 07:42
  • @dbc, this is surely a good practice, but here OP surely need to ensure correct RAM / memory as required by the application, else at a given point even `Dispose` may not help, due to un-detereministic GC invocation – Mrinal Kamboj Sep 26 '16 at 07:44