8

在我的应用程序中,我使用下面提到的帮助方法将我的独立存储图像绑定到图像控件。我从链接“将存储在独立存储中的图像绑定到 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.Windows.ni.dll 中出现“System.OutOfMemoryException”类型的异常,但未在用户代码中处理

堆栈跟踪

在 MS.Internal.FrameworkCallbacks.NotifyManagedDebuggerOnNativeOOM() 在 MS.Internal.XcpImports.BitmapSource_SetSource(BitmapSource bitmapSource, CValue& byteStream) 在 System.Windows.Media.Imaging.BitmapSource.SetSourceInternal(Stream streamSource) 在 System.Windows.Media.Imaging。 BitmapImage.SetSourceInternal(Stream streamSource) 在 System.Windows.Media.Imaging.BitmapSource.SetSource(Stream streamSource) 在 MyaPP.Common.IsoStoreImageSource.<>c__DisplayClass4.<>c__DisplayClass6.b__1(Object _)

4

3 回答 3

0

好的,我花了一些时间才回到这个问题。我将在这里分享我的发现,但我并不认为它们是问题的真正答案,而是一种解决方法。但是,我希望它会对某人有所帮助。

首先,我想确认OutOfMemoryException在某些情况下发生。但是,令人惊讶的是,这取决于您使用的页面布局。事实上,如果你的布局涉及StackPanel,你会有一个例外。我想,这归结为如何实现方法MeasureOverrideArrangeOverride方法的事实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>

这是我现在给你的最好的答案。请让我知道它是否有帮助。

于 2013-04-23T16:11:52.353 回答
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;
         }
     }
}
于 2014-08-05T06:59:22.797 回答
0

中的缓存ListBox可能会占用您的内存,这对于较大的图像尤其明显。我不熟悉您发布的辅助方法,但尝试添加它。

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

    //rest of the code ...
}
于 2013-04-22T12:50:51.903 回答