2010-12-17 4 views
5

. InteropBitmap'in WriteableBitmap'ten daha hızlı olacağını düşündüm: Bellek bölümünden kendini güncelleme yeteneği var.birlikte GDI + ile WPF'ın InteropBitmap: Ben <strong>System.Drawing.Graphics</strong> ve WPF'ın <strong>InteropBitmap</strong> kullanarak bazı rasgele dikdörtgenler her 30 msn kılan küçük wpf testi uygulaması oluşturduk yüksek cpu kullanımı

Uygulamayı çalıştırırken (ekran boyutu 1600 * 1200), cpu kullanımı, çift çekirdekli bir 3GHz ile yalnızca yaklaşık 2-10% olur. Ama genel işlemci kullanımı yaklaşık 80-90%, çünkü "Sistem (NT Kernel & Sistem")% 70'e kadar yükselir! DÜZENLEME: Ve RAM kullanımının, 15 saniye içinde periyodik olarak 1 GB'den fazla arttığını ve sonra aniden normal seviyesine geri döndüğünü fark ettim.

Belki aşağıdaki kod optimize edilebilir? :

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 < 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; 

    } 





}} 

XAML:

<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"> 
    <Image Name="wpfImage" Stretch="None" /> 
</Window> 
+0

Uygulamanızı çalıştırmıyorken bu Sistem işlemi nasıl görünür? Ya da uygulamanız bir kesme noktasına ulaştığında mı? İlk düşüncem bu süreç bir çeşit kötü amaçlı yazılım. –

+0

Sonra herhangi bir cpu tüketmez. Ancak fark ettiğim bir başka şey ise RAM kullanımının 15 saniye içinde periyodik olarak 3 GB'ye yükselmesi ve normal seviyeye düşmesi ve bunun gibi bir şey olmasıdır. Dolayısıyla, her 30 msn'de bellek ayırmadan yüksek cpu kullanımı sonuçları görünüyor (interopbitmap.Invalidate() öğesinin çağrıldığı zamanlayıcı olayı). – fritz

cevap

5

WTF:

http://connect.microsoft.com/VisualStudio/feedback/details/603004/massive-gpu-memory-leak-with-interopbitmap

https://connect.microsoft.com/VisualStudio/feedback/details/585875/interopbitmap-is-way-less-performant-in-net-4-0-vs-net-3-5

: Bu .NET 4.0 yeni sızdırma InteropBitmap bellek bulunuyor

Hedef çerçeveyi 3.5 olarak ayarlamak ve her şey iyi çalışıyor!

Başka bir seçenek "GC.Collect();" her "interopBitmap.Invalidate();" ifadesinden sonra aramak.

İlgili konular