【问题标题】:App crashes while trying to bind the Isolated Storage Image尝试绑定独立存储映像时应用程序崩溃
【发布时间】:2013-04-15 08:13:48
【问题描述】:

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

堆栈跟踪

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

【问题讨论】:

  • 您的列表视图中有多少张图片?他们多大?您可以在您的应用程序(Visual Studio 中的Debug -> Start Windows Phone Application Analysis -> Profiling -> Memory)上运行内存分析并发布您的结果吗?
  • 尝试使用 LongListSelector 作为平面列表
  • @Haspemulator :这里提到了这个问题“stackoverflow.com/questions/15700340/…”、“blogs.developpeur.org/kookiz/archive/2013/02/17/…”,我如何通过你的实现来解决这个问题。
  • 我也面临同样的问题。 @Haspemulator,我执行了内存分析并得到了上述博客中提到的类似响应。您能否更新此问题的解决方案。

标签: windows-phone-7 windows-phone-8 windows-phone


【解决方案1】:

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

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

    //rest of the code ...
}

【讨论】:

    【解决方案2】:

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

    首先我想确认OutOfMemoryException 在某些情况下发生。但是,令人惊讶的是,这取决于您使用的页面布局。事实上,如果你的布局涉及StackPanel,你会有一个例外。我想,这归结为MeasureOverrideArrangeOverride 方法是如何在StackPanel 中实现的(尽管我在这里可能完全错了)。看起来当ListBoxStackPanel 的孩子时,它会尝试在显示之前加载所有图像。这当然会导致内存泄漏。

    另一方面,如果您使用Grid 之类的东西作为图像列表的父级,则不会出现此类异常,并且内存负载是合理的。

    以下是适合我的页面布局:

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

    这是我现在给你的最好的答案。如果有帮助,请告诉我。

    【讨论】:

    • 我认为这不是问题。我也试过这样的东西,
    • 我也试过你提到的上述方法,但结果是一样的.. :(
    【解决方案3】:

    你可以这样尝试,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;
             }
         }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多