2013-04-22 3 views
8

В моем приложении я использую ниже описанный вспомогательный метод для привязки моего изолированного образа хранилища к управлению изображением. Я получил этот вспомогательный метод по ссылке «Binding Image stored in the Isolated Storage to Image Control in Windows Phone»Приложение сбой при попытке привязки изолированного образа хранилища

public class IsoStoreImageSource : DependencyObject 
{ 
public static void SetIsoStoreFileName(UIElement element, string value) 
{ 
    element.SetValue(IsoStoreFileNameProperty, value); 
} 
public static string GetIsoStoreFileName(UIElement element) 
{ 
    return (string)element.GetValue(IsoStoreFileNameProperty); 
} 

// Using a DependencyProperty as the backing store for IsoStoreFileName. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty IsoStoreFileNameProperty = 
    DependencyProperty.RegisterAttached("IsoStoreFileName", typeof(string), typeof(IsoStoreImageSource), new PropertyMetadata("", Changed)); 

private static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    Image img = d as Image; 

    if (img != null) 
    { 
     var path = e.NewValue as string; 
     SynchronizationContext uiThread = SynchronizationContext.Current; 

     Task.Factory.StartNew(() => 
     { 
      using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication()) 
      { 
       if (isoStore.FileExists(path)) 
       { 
        var stream = isoStore.OpenFile(path, System.IO.FileMode.Open, FileAccess.Read); 
        uiThread.Post(_ => 
        { 
         var _img = new BitmapImage(); 
         _img.SetSource(stream); 
         img.Source = _img; 
        }, null); 
       } 
      } 
     });    
    } 
} 

}

Я использую это внутри элемента управления ListBox. И если попробуйте с изображениями библиотеки по умолчанию, все будет работать так, как ожидалось. Но если я попытаюсь с изображениями с большим размером (взятым через камеру устройства), приложение выйдет из строя.

А вот исключение, что я получаю

исключение типа «System.OutOfMemoryException» произошло в System.Windows.ni.dll, но не был обработан в пользовательском коде

трассировки стека

на MS.Internal.FrameworkCallbacks.NotifyManagedDebuggerOnNativeOOM() в MS.Internal.XcpImports.BitmapSource_SetSource (BitmapSource BitmapSource, CValue & потоковый) в System.Windows.Media.Imaging.BitmapSource.SetSourceInternal (Stream Streams ource) в System.Windows.Media.Imaging.BitmapImage.SetSourceInternal (Stream streamSource) в System.Windows.Media.Imaging.BitmapSource.SetSource (поток streamSource) на MyaPP.Common.IsoStoreImageSource. <> c__DisplayClass4. <> c__DisplayClass6.b__1 (Object _)

+0

Сколько изображений вы видите в списке? Насколько они большие?Можете ли вы запустить анализ памяти в своем приложении («Отладка -> Запустить анализ приложений Windows Phone -> Профилирование -> Память» в Visual Studio) и опубликовать результаты? – Haspemulator

+0

Попробуйте использовать LongListSelector как Flat List – Mahantesh

+2

@Haspemulator: проблема упоминается здесь «http://stackoverflow.com/questions/15700340/out-of-memory-exception-while-loading-images-from-isolated-storage» , «http://blogs.developpeur.org/kookiz/archive/2013/02/17/wpdev-memory-leak-with-bitmapimage.aspx», как я могу решить эту проблему с вашей реализацией. –

ответ

0

Кэширование в пределах ListBox может занимать вашу память, и это особенно заметно при использовании больших изображений. Я не знаком с вспомогательным методом, который вы разместили, но попробуйте добавить это.

if (img != null) 
{ 
    BitmapImage bitmapImage = img.Source as BitmapImage; 
    bitmapImage.UriSource = null; 
    img.Source = null; 

    //rest of the code ... 
} 
0

Хорошо, мне потребовалось некоторое время, чтобы вернуться к этой проблеме. Я поделюсь своими выводами здесь, но я не рассматриваю их как реальный ответ на этот вопрос, а скорее обходной путь. Однако я надеюсь, что это поможет кому-то.

Прежде всего, я хочу подтвердить, что OutOfMemoryException происходит в определенных обстоятельствах. Но, что удивительно, это зависит от используемого вами макета страницы. Фактически, если ваш макет включает StackPanel, у вас будет исключение. Я думаю, дело сводится к тому, как методы MeasureOverride и ArrangeOverride реализованы в StackPanel (хотя я могу быть совершенно неправ здесь). Похоже, когда ListBox является ребенком до StackPanel, он пытается загрузить все изображения перед отображением. Это, конечно, вызывает утечку памяти.

С другой стороны, если вы используете что-то вроде Grid в качестве родителя для списка изображений, то таких исключений не существует, и загрузка памяти является разумной.

Вот макет страницы, которые работали для меня:

<Grid> 
    <ListBox ItemsSource="{Binding IsoStorePics}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Image local:IsoStoreImageSource.IsoStoreFileName="{Binding Path}" Margin="5"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
</Grid> 

Это лучший ответ у меня есть для вас сейчас. Пожалуйста, дайте мне знать, если это поможет.

+0

Я думаю, что это не проблема. Я тоже попробовал что-то подобное, <Высота сетки = "350" Ширина = "400" Маржа = "70,0,70,0" x: Название = "Контейнер1">

+0

А также я пробовал описанный выше метод u, но результат такой же .. :( –

0

Вы можете попробовать вот так: объект Stream будет автоматически удален.

using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication()) 
{        
    if (iso.FileExists(imagePath)) 
    { 
     using (Stream imagestream = new IsolatedStorageFileStream(imagePath, FileMode.Open, FileAccess.Read, FileShare.Read, iso)) 
     { 
       BitmapImage bmp = new BitmapImage(); 
       bmp.SetSource(imagestream); 
       imgControl.Source = bmp; 
     } 
    } 
} 
Смежные вопросы