none
Эксепшн "out of memory" в WPF . RRS feed

  • Вопрос

  • Столкнулся с проблемой при использовании кода для gif анимации .
    Все работает, gif проигрывается, но иногда выдает эксепшн  out of memory,

    пытался отследить когда это происходит,но проблема в том что эксепшн выскакивает не всегда.
    Поэтому поводу 2 вопроса:

    1.Что это может быть,как можно решить эту проблему?

    в инете читал что надо явно вызывать Dispose(), но мнения  разнятся,

    кто говорит что garbage collector и так все очистить,  а есть такие что говорят что этого не достаточно.

    2.Где в visual studio 2010 можно посмотреть log (все ошибки которые были в проекте)?

    Код который я использовал:

            ///////////////////////// BackGround_Animation ///////////////////////
    
    
            private BitmapSource GetSource()
            {
                if (_bitmap == null)
                {
                    _bitmap = new Bitmap("earth.gif");
                }
                IntPtr handle = IntPtr.Zero;
                handle = _bitmap.GetHbitmap();
                return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(1020, 760));
    
            }
    
            private void FrameUpdatedCallback()
            {
                ImageAnimator.UpdateFrames();
                if (_source == null)
                {
                    _source.Freeze();
                }
                _source = GetSource();
                this.Background = new ImageBrush(_source);
                InvalidateVisual();
            }
    
            private void OnFrameChanged(object sender, EventArgs e)
            {
                Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback));
                BeginInit();
                EndInit();
            }
    
            void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                BitmapImage bi = new BitmapImage();
    
                bi.BeginInit();
                bi.UriSource = new Uri(@"/earth.gif", UriKind.RelativeOrAbsolute);
                bi.EndInit();
                this.Background = new ImageBrush(bi);
    
                _source = GetSource();
                this.Background = new ImageBrush(_source);
                ImageAnimator.Animate(_bitmap, OnFrameChanged);
            }
    
    
    
            /////////////////////// END background_animation ///////////////////////
    


    • Изменено Konrud 19 февраля 2013 г. 19:35
    19 февраля 2013 г. 19:33

Ответы

  • Суть такова, что вам надо удалить дескриптор точечного рисунка, который создает функция Bitmap.GetHbitmap иначе память, занятая им, не освободится. Можно попробовать примерно так:

    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);
    
    private BitmapSource GetSource()
            {
                if (_bitmap == null)
                {
                    _bitmap = new Bitmap("earth.gif");
                }
                IntPtr handle = IntPtr.Zero;
                handle = _bitmap.GetHbitmap();
                BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(1020, 760));
    
                DeleteObject(handle);
                return bitmapSource;
            }

    • Помечено в качестве ответа Konrud 20 февраля 2013 г. 15:36
    19 февраля 2013 г. 20:18

Все ответы

  • "Пользователь несет ответственность за вызов метода DeleteObject объекта GDI для высвобождения памяти, использованной точечным рисунком GDI."

    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);
    
    
    private void DemonstrateGetHbitmap()
    {
        Bitmap bm = new Bitmap("Picture.jpg");
        IntPtr hBitmap = bm.GetHbitmap();
    
        // Do something with hBitmap.
        DeleteObject(hBitmap);
    }

    У вас просто заканчивается память и вы ее не освобождаете.

    19 февраля 2013 г. 19:43
  • спасибо за такой быстрый ответ,
    хотелось бы поподробнее,
     я слышал что это надо делать в try{} catch{} 
    и при этом использовать Dispose() в finally{}?
    где именно в коде который я использую нужно делать вызов удаления объекта,
    я новичок в C# , буду благодарен за помощь.
    спасибо.
    19 февраля 2013 г. 20:01
  • Суть такова, что вам надо удалить дескриптор точечного рисунка, который создает функция Bitmap.GetHbitmap иначе память, занятая им, не освободится. Можно попробовать примерно так:

    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);
    
    private BitmapSource GetSource()
            {
                if (_bitmap == null)
                {
                    _bitmap = new Bitmap("earth.gif");
                }
                IntPtr handle = IntPtr.Zero;
                handle = _bitmap.GetHbitmap();
                BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(1020, 760));
    
                DeleteObject(handle);
                return bitmapSource;
            }

    • Помечено в качестве ответа Konrud 20 февраля 2013 г. 15:36
    19 февраля 2013 г. 20:18
  • Посмотрите эту тему. Там я привожу пример из официальной библиотеки примеров VisualStudio и он кстати содержит очистку хэндлов

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    20 февраля 2013 г. 5:39
  • Спасибо за ответ. буду пробовать.

     вот этот код:
    [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject);   

    это что, не похоже на namespace?

    для чего он?
    Вы уж не обессудьте,  я новичок в программировании и хотелось бы не просто переписать код,  а понять его.
    Спасибо.

    20 февраля 2013 г. 15:34
  • Спасибо за ответ,  но только это если я не ошибаюсь написано на VB а мне бы C# код.
    мне нужно знать где мне очистку памяти в код вставить.

    хотелось бы не просто переписать код,  а понять его.

    Спасибо.

    20 февраля 2013 г. 15:35
  • По этому поводу вы можете почитать здесь. Если кратко - это импорт функции из динамической библиотеки, которая не является сборкой .NET
    20 февраля 2013 г. 17:18