带自动内存清理功能的图片下载器详情页面打开)。我已经在此处、此处、此处和此处描述了相当著名的图像内存泄漏问题。一种可能的方法是在NavigatingFrom时浏览所有图像并清除它们。在其中一个线程中,我发现了一个更有趣的解决方案:它会自动清理图像,但这不适用于虚拟化(图像丢失或混合,如果您添加一个用于存储ImageSource的私有字段)。建议的解决方法是添加依赖属性。但我仍然面临同样的问题:向下和向后滚动后图像变得混乱。看起来依赖属性在随机变化,但我无法捕捉到它们变化的时刻。公共类SafePicture:ContentControl{publicstaticreadonlyDependencyPropertySafePathProperty=DependencyProperty.RegisterAttached("SafePath",typeof(string),typeof(SafePicture),newPropertyMetadata(OnSourceWithCustomRefererChanged));publicstringSafePath{get{return(string)GetValue(SafePathProperty);}set{SetValue(SafePathProperty,value);}}privatestaticvoidOnSourceWithCustomRefererChanged(DependencyObjecto,DependencyPropertyChangedEventArgse){if(e.NewValue==null)//这里的新值return;}publicSafePicture(){Content=newImage();已加载+=已加载;卸载+=OnUnloaded;}privatevoidOnLoaded(object_sender,RoutedEventArgs_routedEventArgs){varimage=ContentasImage;如果(图像==null)返回;varpath=(string)GetValue(SafePathProperty);//此外,尝试了SafePath(调试器无法捕获setter和getter调用),但结果相同。图片.Source=null;{varrequest=WebRequest.Create(path)asHttpWeb请求;request.AllowReadStreamBuffering=true;request.BeginGetResponse(result=>{try{StreamimageStream=request.EndGetResponse(result).GetResponseStream();DispatcherHelper.CheckBeginInvokeOnUI(()=>{if(imageStream==null){image.Source=newBitmapImage{UriSource=newUri(path,UriKind.Relative)};return;}varbitmapImage=newBitmapImage();bitmapImage.CreateOptions=BitmapCreateOptions.BackgroundCreation;bitmapImage.SetSource(imageStream);image.Source=bitmapImage;});}赶上(WebException){}},无效的);}}privatevoidOnUnloaded(objectsender,RoutedEventArgse){varimage=ContentasImage;如果(图像==null)返回;var位图图像=图像。来源为BitmapImage;如果(bitmapImage!=null)bitmapImage.UriSource=null;图片.Source=null;用法:所以乍一看,它工作正常,但如果你向下和向后滚动,图像会随机变化编辑:在这种情况下,目前,我只是使用一个没有虚拟化的纯ListBox).EDIT2:重现问题的示例项目。我相信,它会包含一段时间的解决方案:https://simca.codeplex.com/问题是当使用虚拟化时,用于每个项目的ui元素被回收并重新用于其他对象(因此包括图像对象),并且由于当您滚动得足够快时图像是异步加载的,因此您将为已经被另一个项目重用的图像设置位图。快速修复只是检查路径值是否仍然相同,如果不相同,则返回,因为图像已被另一个对象重用:...varrequest=WebRequest.Create(path)asHttpWebRequest;request.AllowReadStreamBuffering=true;request.BeginGetResponse(result=>{try{StreamimageStream=request.EndGetResponse(result).GetResponseStream();DispatcherHelper.CheckBeginInvokeOnUI(()=>{if(path!=SafePath){//Item已被回收return;}...。编辑:代码中有几个问题:-将RegisterAttached切换到Register,RegisterAttached用于附加属性而不是正常的依赖属性-在OnSourceWithCustomRefererChanged中调用OnLoaded因为SafePath属性更改实际上可以在加载元素后很高兴-添加clearuriandThesource在onLoaded的开头,当路径为空时清除图像下面是一个完整的工作代码:,typeof(string),typeof(SafeImage),newPropertyMetadata(default(string),OnSourceWithCustomRefererChanged));publicstringSafePath{get{return(string)GetValue(SafePathProperty);}}设置{SetValue(SafePathProperty,value);}}privatestaticvoidOnSourceWithCustomRefererChanged(DependencyObjecto,DependencyPropertyChangedEventArgse){SafeImagesafeImage=oasSafeImage;safeImage.OnLoaded(null,null);//OnLoaded(null,null);如果(e.NewValue==null)返回;}publicSafeImage(){Content=newImage();uiThread=SynchronizationContext.Current;已加载+=已加载;卸载+=OnUnloaded;}privatevoidOnLoaded(object_sender,RoutedEventArgs_routedEventArgs){varimage=ContentasImage;如果(图像==null)返回;变种路径=安全路径;//(字符串)GetValue(SafePathProperty);//image.Source=newBitmapImage(newUri(SafePath));Debug.WriteLine(路径);varbitmapImage=image.SourceasBitmapImage;如果(bitmapImage!=null)bitmapImage.UriSource=null;图片.Source=null;if(String.IsNullOrEmpty(path)){//image.Source=newBitmapImage{UriSource=newUri(Constants.RESOURCE_IMAGE_EMPTY_PRODUCT,UriKind.Relative)};关于转动;}//如果是本地图片,只加载它(非本地图片路径以“http”开头)if(path.StartsWith("/")){image.Source=newBitmapImage{UriSource=newUri(path,UriKind.相对的)};返回;}{varrequest=WebRequest.Create(path)asHttpWebRequest;request.AllowReadStreamBuffering=true;request.BeginGetResponse(result=>{try{StreamimageStream=request.EndGetResponse(result).GetResponseStream();uiThread.Post(_=>{if(path!=this.SafePath){return;}if(imageStream==null){image.Source=newBitmapImage{UriSource=newUri(path,UriKind.Relative)};return;}bitmapImage=newBitmapImage();bitmapImage.CreateOptions=BitmapCreateOptions.BackgroundCreation;bitmapImage.SetSource(imageStream);图片。Source=bitmapImage;//imageCache.Add(path,bitmapImage);},null);}catch(WebException){//uiThread.Post(_=>//{//image.Source=newBitmapImage{UriSource=new}Uri(常量.RESOURCE_IMAGE_EMPTY_PRODUCT,UriKind。相对的)};//},无效的);}},无效的);}}privatevoidOnUnloaded(objectsender,RoutedEventArgse){varimage=ContentasImage;如果(图像==null)返回;varbitmapImage=image.SourceasBitmapImage;如果(bitmapImage!=null)bitmapImage.UriSource=null;图片.Source=null;}}最后,WindowsPhoneListBox默认使用虚拟化和回收(使用的ItemPanel是VirtualisedStackPanel)以上是C#学习教程:带内存自动清理功能的图片下载器分享的所有内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
