c# – OutOfMemoryException @ WriteableBitmap @后台代理
我有一个
Windows Phone 8应用程序,它使用后台代理:
>从互联网获取数据; 但是,当它在后台运行时,它会得到OutOfMemoryException,到目前为止一些故障排除: >当我在“前线”中运行该过程时,一切正常; – 限制是11,534,336(位) – 当后台代理启动时,即使没有任何任务,内存使用量也变为4,648,960 – 从互联网获得更新时,它增长到5,079,040 – 完成后,它回落到4,960 – 当调用开始时(从用户控件生成图像),它增长到8,499,200 好吧,我想这就是问题所在,通过WriteableBitmap呈现图像的内存很少. 知道如何解决这个问题吗? 有没有更好的方法从用户控件/或其他任何东西生成图像? 实际上原始图像可能只有100 kb左右,但是,当通过WriteableBitmap进行渲染时,文件大小(以及我猜想的所需内存大小)可能会增长到1-2MB. 或者我可以从任何地方释放内存吗? ================================================== ============ 顺便说一句,当这个Code Project article说我只能在周期性任务中使用11MB内存时; 但是,这个MSDN article表示我可以使用Windows Phone 8 Update 3最多20 MB或25 MB; ================================================== ============ 编辑: 说到调试器,它也在MSDN article中说明: 在调试器下运行时,将暂停内存和超时限制. 但为什么我仍然会遇到限制? ================================================== ============ 编辑: 好吧,我发现似乎有些帮助,我现在就检查一下,建议仍然受欢迎. http://writeablebitmapex.codeplex.com/ http://suchan.cz/2012/07/pro-live-tiles-for-windows-phone/ http://notebookheavy.com/2011/12/06/microsoft-style-dynamic-tiles-for-windows-phone-mango/ ================================================== ============ 生成图像的代码: Deployment.Current.Dispatcher.BeginInvoke(() => { var customBG = new ImageUserControl(); customBG.Measure(new Size(480,800)); var bmp = new WriteableBitmap(480,800); //Thrown the **OutOfMemoryException** bmp.Render(customBG,null); bmp.Invalidate(); using (var isf = IsolatedStorageFile.GetUserStoreForApplication()) { filename = "/Shared/NewBackGround.jpg"; using (var stream = isf.OpenFile(filename,System.IO.FileMode.OpenOrCreate)) { bmp.SaveJpeg(stream,480,800,100); } } } ImageUserControl的XAML代码: <UserControl blabla... d:DesignHeight="800" d:DesignWidth="480"> <Grid x:Name="LayoutRoot"> <Image x:Name="nBackgroundSource" Stretch="UniformToFill"/> //blabla... </Grid> </UserControl> ImageUserControl背后的C#代码: public ImageUserControl() { InitializeComponent(); LupdateUI(); } public void LupdateUI() { DataInfo _dataInfo = new DataInfo(); LayoutRoot.DataContext = _dataInfo; try { using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication()) { using (var isoFileStream = isoStore.OpenFile("/Shared/BackgroundImage.jpg",FileMode.Open,FileAccess.Read)) { BitmapImage bi = new BitmapImage(); bi.SetSource(isoFileStream); nBackgroundSource.Source = bi; } } } catch (Exception) { } } 当DataInfo是settings page中保存数据的另一个类来自互联网时: public class DataInfo { public string Wind1 { get { return GetValueOrDefault<string>("Wind1","N/A"); } set { if (AddOrUpdateValue("Wind1",value)) { Save(); } } } public string Wind2 { get { return GetValueOrDefault<string>("Wind2","N/A"); } set { if (AddOrUpdateValue("Wind2",value)) { Save(); } } } //blabla... } 解决方法
如果我注释掉更新进度,它也可以正常工作我认为你应该专注于那部分.它似乎表明更新后没有释放一些内存.在渲染图片之前,请确保更新过程中使用的所有引用都超出范围.强制垃圾收集也有帮助:
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); // Frees the memory that was used by the finalizers 另一件需要考虑的事情是调试器也使用了大量内存.通过在“发布”模式下编译项目并在手机上部署以确保内存不足来进行真正的测试. 尽管如此,我已经处于这种状况,所以我知道这可能还不够.关键是:.NET Framework中的某些库是懒惰加载的.例如,如果您的更新过程涉及下载某些数据,则后台代理将加载网络库.这些库无法卸载,会浪费一些代理的内存.这就是为什么即使释放您在更新过程中使用的所有内存,也不会达到启动后台代理时所用的相同数量的可用内存.看到这一点,我在我的一个应用程序中所做的是跨两次执行跨越后台代理的工作量.基本上,代理执行时: >如果要处理待处理数据,请检查隔离存储.如果没有,只需执行更新过程并将所有需要的数据存储在隔离存储中 这意味着图片每小时只生成一次,而不是每30分钟生成一次,因此只有在其他一切都失败的情况下才使用此解决方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |