title: Wpf's InteropBitmap together with GDI+: high cpu usage
body: <p>I've created a little wpf test application which renders some random rectangles every 30 msec using <strong>System.Drawing.Graphics</strong> and wpf's <strong>InteropBitmap</strong>. I thought InteropBitmap would be faster than WriteableBitmap: It has the ability to update itself from the memory section.</p>
  
  <p>While executing the app (screen size 1600 * 1200)  the cpu usage of the app is only about <strong>2-10%</strong> with a dual core 3GHz. But the overall cpu usage is about <strong>80-90%</strong>, because the process "System (NT Kernel &amp; System") rises up to 70% ! <strong>EDIT:</strong> And I noticed that the RAM usage periodically increases by more than 1 GB within 15 seconds and then suddenly falls back to its normal level and so on.</p>
  
  <p>Maybe the following code can be optimized ? :</p>
  
  <pre><code>namespace InteropBitmapTest{
  
   using System;
   using System.Drawing;
   using System.Runtime.InteropServices;
   using System.Windows;
   using System.Windows.Interop;
   using System.Windows.Media;
   using System.Windows.Media.Imaging;
   using Color = System.Drawing.Color;
  
  public partial class Window1 : Window
  {
  
      private System.Drawing.Bitmap gdiBitmap;
      private Graphics graphics;
  
  
      InteropBitmap interopBitmap;
  
      const uint FILE_MAP_ALL_ACCESS = 0xF001F;
      const uint PAGE_READWRITE = 0x04;
  
      private int bpp = PixelFormats.Bgr32.BitsPerPixel / 8;
  
      private Random random;
      private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
  
  
      SolidBrush[] brushes = new SolidBrush[] { new SolidBrush(Color.Lime), new SolidBrush(Color.White) };
  
  
      [DllImport("kernel32.dll", SetLastError = true)]
      static extern IntPtr CreateFileMapping(IntPtr hFile,
      IntPtr lpFileMappingAttributes,
      uint flProtect,
      uint dwMaximumSizeHigh,
      uint dwMaximumSizeLow,
      string lpName);
  
      [DllImport("kernel32.dll", SetLastError = true)]
      static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject,
      uint dwDesiredAccess,
      uint dwFileOffsetHigh,
      uint dwFileOffsetLow,
      uint dwNumberOfBytesToMap);
  
      public Window1()
      {
          InitializeComponent();
  
          Loaded += Window1_Loaded;
  
          WindowState = WindowState.Maximized;
  
          timer.Tick += timer_Tick;
          timer.Interval = 30;
  
          random = new Random();
  
      }
  
      void Window1_Loaded(object sender, RoutedEventArgs e)
      {
          // create interopbitmap, gdi bitmap, get Graphics object
          CreateBitmaps();
  
  
          // start drawing 100 gdi+ rectangles every 30 msec:
          timer.Start();
      }
  
  
      void timer_Tick(object sender, EventArgs e)
      {
          int width = 50;
  
  
          // Draw 100 gdi+ rectangles :
  
  
          for (int i = 0; i &lt; 100; i++)
          {
              int left = random.Next((int)(ActualWidth - width));
              int top = random.Next((int)(ActualHeight - width));
  
  
              graphics.FillRectangle(brushes[left % 2], left, top, width, width);
  
          }
  
  
          interopBitmap.Invalidate(); // should only update video memory (and not copy the whole bitmap to video memory before)
  
      }
  
  
      void CreateBitmaps()
      {
  
          uint byteCount = (uint) (ActualWidth * ActualHeight * bpp);
  
  
          //Allocate/reserve memory to write to
  
          var sectionPointer = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, PAGE_READWRITE, 0, byteCount, null);
  
          var mapPointer = MapViewOfFile(sectionPointer, FILE_MAP_ALL_ACCESS, 0, 0, byteCount);
  
          var format = PixelFormats.Bgr32;
  
          //create the InteropBitmap
  
          interopBitmap = Imaging.CreateBitmapSourceFromMemorySection(sectionPointer, (int)ActualWidth, (int)ActualHeight, format,
              (int)(ActualWidth * format.BitsPerPixel / 8), 0) as InteropBitmap;
  
  
          //create the GDI Bitmap
  
          gdiBitmap = new System.Drawing.Bitmap((int)ActualWidth, (int)ActualHeight,
                                      (int)ActualWidth * bpp,
                                       System.Drawing.Imaging.PixelFormat.Format32bppPArgb,
                                      mapPointer);
  
          // Get good old GDI Graphics
  
          graphics = Graphics.FromImage(gdiBitmap);
  
  
          // set the interopbitmap as Source to the wpf image defined in XAML 
  
          wpfImage.Source = (BitmapSource) interopBitmap; 
  
      }
  
  
  
  
  
  }}
  </code></pre>
  
  <p>XAML:</p>
  
  <pre><code>&lt;Window x:Class="InteropBitmapTest.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Window1" Height="300" Width="300"&gt;
    &lt;Image Name="wpfImage" Stretch="None" /&gt;
  &lt;/Window&gt;
  </code></pre>