Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. WPF
  4. WPF memory leak BitmapImage

WPF memory leak BitmapImage

Scheduled Pinned Locked Moved WPF
csharpc++wpfgraphicshardware
17 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Lost User

    You're trying to create an image from an "empty" memory stream; key statement missing:

            bitmap.Save( memory, System.Drawing.Imaging.ImageFormat.Bmp );
    

    "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

    L Offline
    L Offline
    Leif Simon Goodwin
    wrote on last edited by
    #6

    Thanks for spotting that, it actually isn't missing in our code, but it is missing from the sample I pasted here. Ooops. Sorry about that.

    L 1 Reply Last reply
    0
    • realJSOPR realJSOP

      Are all machines running exactly the same version of .Net?

      ".45 ACP - because shooting twice is just silly" - JSOP, 2010
      -----
      You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
      -----
      When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013

      L Offline
      L Offline
      Leif Simon Goodwin
      wrote on last edited by
      #7

      I will check.

      1 Reply Last reply
      0
      • M MadMyche

        As previously suggested, check the .NET versions on the machines; there have been a few issues that vary by version. I would probably try moving the creation of the BitmapImage outside of the `using` block, or try some garbage collection routines, or object disposal to see what kind of response you get from what methods


        Director of Transmogrification Services Shinobi of Query Language Master of Yoda Conditional

        L Offline
        L Offline
        Leif Simon Goodwin
        wrote on last edited by
        #8

        Oh, I was hoping .Net would be solid. How on earth do we ensure that customers have a bug free version, if that is the cause?

        M 1 Reply Last reply
        0
        • L Leif Simon Goodwin

          Thanks for spotting that, it actually isn't missing in our code, but it is missing from the sample I pasted here. Ooops. Sorry about that.

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #9

          Then maybe you're also running "different" versions of the app ... (I like to put the version # in the title bar).

          "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

          L 1 Reply Last reply
          0
          • L Leif Simon Goodwin

            Oh, I was hoping .Net would be solid. How on earth do we ensure that customers have a bug free version, if that is the cause?

            M Offline
            M Offline
            MadMyche
            wrote on last edited by
            #10

            First you must ensure that your code in itself is bug free.


            Director of Transmogrification Services Shinobi of Query Language Master of Yoda Conditional

            L 1 Reply Last reply
            0
            • L Lost User

              Then maybe you're also running "different" versions of the app ... (I like to put the version # in the title bar).

              "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

              L Offline
              L Offline
              Leif Simon Goodwin
              wrote on last edited by
              #11

              No, just stupidity on my part when copying code to this forum.

              1 Reply Last reply
              0
              • M MadMyche

                First you must ensure that your code in itself is bug free.


                Director of Transmogrification Services Shinobi of Query Language Master of Yoda Conditional

                L Offline
                L Offline
                Leif Simon Goodwin
                wrote on last edited by
                #12

                MadMyche wrote:

                First you must ensure that your code in itself is bug free.

                If I simply discard the BitmapImage created by the quoted code, rather than saving it, the memory leak is present.

                1 Reply Last reply
                0
                • L Leif Simon Goodwin

                  We have some code which receives images of a document from a C++ DLL, and displays them in a WPF application. The C# code stores the images in an array, which it flushes each time a new document is placed on the scanner. The code converts the image from a Bitmap to a BitmapImage, which is the image type for display in WPF:

                      private BitmapImage CreateBitmapImage(Bitmap bitmap)
                      {
                          using (MemoryStream memory = new MemoryStream())
                          {
                              bitmap.Save(memory, ImageFormat.Bmp);
                              memory.Position = 0;
                              BitmapImage bitmapimage = new BitmapImage();
                              bitmapimage.BeginInit();
                              bitmapimage.StreamSource = memory;
                              bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                              bitmapimage.EndInit();
                              bitmapimage.Freeze();
                              return bitmapimage;
                          }
                      }
                  

                  The above code leaks, but only on some PCs. On most it is okay. It can be fine on one Windows 10 PC, and leak on another that has Windows 10 on the same hardware. A key point to note is that the DLL module is also passing the bitmap handle to a third party validation DLL, and if we remove that DLL, the memory leak disappears. If I remove the Freeze() call, the code does not leak, but the images are not displayed. If I comment out the return call, and return null instead, the code still leaks. Therefore the issue is not that we do not clear the stored images. That this only occurs on some PCs, might suggest a timing issue associated with the validation DLL. Thoughts? :) Note: Edited to correct the code. For some reason I'd copied it with a key line missing!

                  L Offline
                  L Offline
                  Leif Simon Goodwin
                  wrote on last edited by
                  #13

                  I have 'solved' the memory leak in our products but I don't understand why. This is a snippet of the code: MemoryStream memoryStream = (_bitmapImages[index] != null) ? (_bitmapImages[index].StreamSource as MemoryStream): new MemoryStream(); _bitmapImages[index] = CreateBitmapImage(bitmap, memoryStream); The modified CreateBitmapImage method takes a MemoryStream instance as an argument. We retain our images for a short time, and then clear them. If a new image arrives before the previous one has been cleared, we reuse the MemoryStream from the old one. Note that the above ignores issues with threading and serialising access to the _bitmapImages[index] value, as I wanted to keep the snippet simple. This solves our memory leak, but not understanding why is concerning.

                  1 Reply Last reply
                  0
                  • L Leif Simon Goodwin

                    We have some code which receives images of a document from a C++ DLL, and displays them in a WPF application. The C# code stores the images in an array, which it flushes each time a new document is placed on the scanner. The code converts the image from a Bitmap to a BitmapImage, which is the image type for display in WPF:

                        private BitmapImage CreateBitmapImage(Bitmap bitmap)
                        {
                            using (MemoryStream memory = new MemoryStream())
                            {
                                bitmap.Save(memory, ImageFormat.Bmp);
                                memory.Position = 0;
                                BitmapImage bitmapimage = new BitmapImage();
                                bitmapimage.BeginInit();
                                bitmapimage.StreamSource = memory;
                                bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                                bitmapimage.EndInit();
                                bitmapimage.Freeze();
                                return bitmapimage;
                            }
                        }
                    

                    The above code leaks, but only on some PCs. On most it is okay. It can be fine on one Windows 10 PC, and leak on another that has Windows 10 on the same hardware. A key point to note is that the DLL module is also passing the bitmap handle to a third party validation DLL, and if we remove that DLL, the memory leak disappears. If I remove the Freeze() call, the code does not leak, but the images are not displayed. If I comment out the return call, and return null instead, the code still leaks. Therefore the issue is not that we do not clear the stored images. That this only occurs on some PCs, might suggest a timing issue associated with the validation DLL. Thoughts? :) Note: Edited to correct the code. For some reason I'd copied it with a key line missing!

                    L Offline
                    L Offline
                    Leif Simon Goodwin
                    wrote on last edited by
                    #14

                    Thanks to everyone who replied. I believe that I have solved this. The code behaves as if the MemoryStream Dispose method is never called. So the obvious fix is to explicitly dispose of the stream:

                        void ClearBitmapImage(int type)
                        {
                            if (\_myBitmapImages\[type\] != null)
                            {
                                System.IO.Stream stream = \_myBitmapImages\[type\].Bitmap.StreamSource;
                                \_myBitmapImages\[type\].Bitmap = null;
                                stream.Dispose();
                                \_myBitmapImages\[type\] = null;
                            }
                        }
                    

                    The Bitmap property is an instance of BitmapImage. I also do a collect as otherwise it takes an age to clean up the memory:

                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                    

                    I still do not understand why we do not see this unless we are using a third party validation DLL!

                    1 Reply Last reply
                    0
                    • L Leif Simon Goodwin

                      We have some code which receives images of a document from a C++ DLL, and displays them in a WPF application. The C# code stores the images in an array, which it flushes each time a new document is placed on the scanner. The code converts the image from a Bitmap to a BitmapImage, which is the image type for display in WPF:

                          private BitmapImage CreateBitmapImage(Bitmap bitmap)
                          {
                              using (MemoryStream memory = new MemoryStream())
                              {
                                  bitmap.Save(memory, ImageFormat.Bmp);
                                  memory.Position = 0;
                                  BitmapImage bitmapimage = new BitmapImage();
                                  bitmapimage.BeginInit();
                                  bitmapimage.StreamSource = memory;
                                  bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                                  bitmapimage.EndInit();
                                  bitmapimage.Freeze();
                                  return bitmapimage;
                              }
                          }
                      

                      The above code leaks, but only on some PCs. On most it is okay. It can be fine on one Windows 10 PC, and leak on another that has Windows 10 on the same hardware. A key point to note is that the DLL module is also passing the bitmap handle to a third party validation DLL, and if we remove that DLL, the memory leak disappears. If I remove the Freeze() call, the code does not leak, but the images are not displayed. If I comment out the return call, and return null instead, the code still leaks. Therefore the issue is not that we do not clear the stored images. That this only occurs on some PCs, might suggest a timing issue associated with the validation DLL. Thoughts? :) Note: Edited to correct the code. For some reason I'd copied it with a key line missing!

                      L Offline
                      L Offline
                      Leif Simon Goodwin
                      wrote on last edited by
                      #15

                      I've come across the source for one version of MemoryStream: Reference Source[^] The interesting feature here is that the Dispose method does NOT set the buffer reference to null. That seems a bizarre choice.

                      1 Reply Last reply
                      0
                      • L Leif Simon Goodwin

                        We have some code which receives images of a document from a C++ DLL, and displays them in a WPF application. The C# code stores the images in an array, which it flushes each time a new document is placed on the scanner. The code converts the image from a Bitmap to a BitmapImage, which is the image type for display in WPF:

                            private BitmapImage CreateBitmapImage(Bitmap bitmap)
                            {
                                using (MemoryStream memory = new MemoryStream())
                                {
                                    bitmap.Save(memory, ImageFormat.Bmp);
                                    memory.Position = 0;
                                    BitmapImage bitmapimage = new BitmapImage();
                                    bitmapimage.BeginInit();
                                    bitmapimage.StreamSource = memory;
                                    bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                                    bitmapimage.EndInit();
                                    bitmapimage.Freeze();
                                    return bitmapimage;
                                }
                            }
                        

                        The above code leaks, but only on some PCs. On most it is okay. It can be fine on one Windows 10 PC, and leak on another that has Windows 10 on the same hardware. A key point to note is that the DLL module is also passing the bitmap handle to a third party validation DLL, and if we remove that DLL, the memory leak disappears. If I remove the Freeze() call, the code does not leak, but the images are not displayed. If I comment out the return call, and return null instead, the code still leaks. Therefore the issue is not that we do not clear the stored images. That this only occurs on some PCs, might suggest a timing issue associated with the validation DLL. Thoughts? :) Note: Edited to correct the code. For some reason I'd copied it with a key line missing!

                        L Offline
                        L Offline
                        Leif Simon Goodwin
                        wrote on last edited by
                        #16

                        I've come across the source for MemoryStream which shows that the Dispose method does NOT set the buffer reference to null. And I can work around the memory leak by assigning a persistent buffer to the MemoryStream instance instead of allowing it to allocate its own buffer. I still don't fully understand what is happening. :(

                        1 Reply Last reply
                        0
                        • L Leif Simon Goodwin

                          We have some code which receives images of a document from a C++ DLL, and displays them in a WPF application. The C# code stores the images in an array, which it flushes each time a new document is placed on the scanner. The code converts the image from a Bitmap to a BitmapImage, which is the image type for display in WPF:

                              private BitmapImage CreateBitmapImage(Bitmap bitmap)
                              {
                                  using (MemoryStream memory = new MemoryStream())
                                  {
                                      bitmap.Save(memory, ImageFormat.Bmp);
                                      memory.Position = 0;
                                      BitmapImage bitmapimage = new BitmapImage();
                                      bitmapimage.BeginInit();
                                      bitmapimage.StreamSource = memory;
                                      bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                                      bitmapimage.EndInit();
                                      bitmapimage.Freeze();
                                      return bitmapimage;
                                  }
                              }
                          

                          The above code leaks, but only on some PCs. On most it is okay. It can be fine on one Windows 10 PC, and leak on another that has Windows 10 on the same hardware. A key point to note is that the DLL module is also passing the bitmap handle to a third party validation DLL, and if we remove that DLL, the memory leak disappears. If I remove the Freeze() call, the code does not leak, but the images are not displayed. If I comment out the return call, and return null instead, the code still leaks. Therefore the issue is not that we do not clear the stored images. That this only occurs on some PCs, might suggest a timing issue associated with the validation DLL. Thoughts? :) Note: Edited to correct the code. For some reason I'd copied it with a key line missing!

                          L Offline
                          L Offline
                          Leif Simon Goodwin
                          wrote on last edited by
                          #17

                          Thank you to everyone for your thoughts. It appears to be unrelated to the version of .Net. I found the source for MemoryStream and the Dispose method does NOT set the buffer reference to null. I tried assigning a static buffer to the MemoryStream instance instead of allowing it to allocate its own buffer but that caused a crash. I created test WPF and WinForms apps and the results are bizarre. We have a small C# class - VideoOCRWrapper - which drives an attached OCR document scanner. It essentially makes calls to a C++ DLL, and has a callback which receives a IntPtr containing a HWND. On receipt of a bitmap, it converts it to a BitmapImage and fires an event to provide a client with the BitmapImage isntance. I created a WinForms app, which initialises VideoOCRWrapper and displays the received bitmap. It has converts the BitmapImage to a Bitmap for display.It shows no memory leaks. I created a WPF app, which initialises VideoOCRWrapper and displays the received bitmap. It shows a huge memory leak consistent with the bitmap buffer leaking. The two apps use almost the same code, except that the WinForms overrides the form's WndProc, whereas the WPF app hooks its own WndProc onto the main window. I memory profiled the WPF test app, and it said that "22 types have instances that are queued for finalization. This can indicate that a Finalizer method is stuck, which will prevent instances from being finalized and cause memory leaks.". There is an extra factor. We use a third party DLL for document verification, which receives bitmaps from us. If I remove that DLL, our code shows no leaks. If I add that DLL, we have leaks but only when running our WPF test app, or our WPF application. When running the WinForms test app, we have no leaks.

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups