1

I have a function that returns an array of bytes containing the data of a bmp img live from a camera (including header). I write that array in to a MemoryStream object. That object, I pass to a Image object constructor, which will be passed to a PictureBox.

tl;dr:

byte[] AoB = GetImage();
MemoryStream ms = new MemoryStream();
ms.Write(AoB, 0, AoB.Length);
pictureBoxImage.Image = Image.FromStream(ms);
ms.Dispose();

All of this is done in a timer with a delay of 200 ms (5fps). It works fine for about a minute or 2 until OutOfMemory exception. For some reason, even though I dispose of the memory used, it keeps generating new one. I've also tried to declare ms as global and flush it every time, still no go. How can I stream the images while using the same memory space?

Sharon Dorot
  • 542
  • 1
  • 4
  • 15

3 Answers3

2

Try disposing the Image objects when you're done with them as well:

byte[] AoB = GetImage();
using (MemoryStream ms = new MemoryStream()) {
    ms.Write(AoB, 0, AoB.Length);
    Image old = pictureBoxImage.Image;
    pictureBoxImage.Image = Image.FromStream(ms);
    if (old != null) {
        old.Dispose();
    }
}
adv12
  • 8,443
  • 2
  • 24
  • 48
1

You definitely should dispose the old images when you are done with them (as adv12 mentioned), however you are also creating two byte[]s in memory. The first one is the one you get from GetImage() the second one is the one stored inside the MemoryStream and that one could be larger than your source array due to its growing algorithms.

Instead use this overload of the MemoryStream constructor to allow you to pass the byte[] directly in and the MemoryStream will reuse that single array for its internal store, reducing the memory requirement.

byte[] AoB = GetImage();
using (MemoryStream ms = new MemoryStream(AoB)) {
    Image old = pictureBoxImage.Image;
    pictureBoxImage.Image = Image.FromStream(ms);
    old.Dispose();
}
Community
  • 1
  • 1
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Unfortunately it didn't work... It managed to slow it down a bit but it still builds up the memory and crashes. I guess I'll have to use a C++ dll or unsafe snippet... Unless you have any other ideas? – Sharon Dorot Jan 29 '14 at 20:16
  • @SharonJDDorot, if the above didn't fix your leak, I would guess the problem is in the GetImage method. Have you tried calling GetImage() repeatedly without any of the other code? – adv12 Jan 29 '14 at 20:28
  • The GetImage() function doesn't really exist, it's listed to cover un-related code that will result in the image array. What it does is read the bytes from the sensor, re-arrange them in order for colored image and add the BMP header. Yes, I have done it in a loop and dumped it to a file instead of MemoryStream and it was fine. – Sharon Dorot Jan 29 '14 at 20:29
0

Try setting your timer's AutoReset=false and manually starting it over at the end of the last call.

myTimer.AutoReset = false;

Start after image assignment.

byte[] AoB = GetImage();
MemoryStream ms = new MemoryStream();
ms.Write(AoB, 0, AoB.Length);
pictureBoxImage.Image = Image.FromStream(ms);
ms.Dispose();
myTimer.Start().

The timer has the potential to get ahead of the retrieval of the images.

Felix Castor
  • 1,598
  • 1
  • 18
  • 39
  • Multiple threads? Do we know what sort of timer she's using? If it's a Windows Forms timer, it should only call back on the GUI thread... – adv12 Jan 29 '14 at 17:13