C# OutOfMemoryException@WriteableBitmap@background agent

C# OutOfMemoryException@WriteableBitmap@background agent,c#,windows-phone-8,writeablebitmap,C#,Windows Phone 8,Writeablebitmap,我有一个Windows Phone 8应用程序,它使用后台代理来: 从互联网上获取数据 基于使用步骤1中的数据作为数据源的用户控件生成图像 在用户控件中,我有Grid&StackPanel和一些文本和图像控件 当某些映像使用安装文件夹(/Assets/Images/…)中的本地资源时 其中一个我用作背景的是用户从手机的照片库中选择的,所以我必须使用C#代码来设置源代码 但是,当它在后台运行时,它会得到OutOfMemoryException,目前有一些疑难解答: 当我在“前线”运行流程时,一切正

我有一个Windows Phone 8应用程序,它使用后台代理来:

  • 从互联网上获取数据
  • 基于使用步骤1中的数据作为数据源的用户控件生成图像
  • 在用户控件中,我有Grid&StackPanel和一些文本和图像控件
  • 当某些映像使用安装文件夹(/Assets/Images/…)中的本地资源时 其中一个我用作背景的是用户从手机的照片库中选择的,所以我必须使用C#代码来设置源代码
  • 但是,当它在后台运行时,它会得到
    OutOfMemoryException
    ,目前有一些疑难解答:

  • 当我在“前线”运行流程时,一切正常
  • 如果我评论出更新进度,并直接创建图像,它也可以正常工作
  • 如果我不设置背景图像,它也可以正常工作
  • OutOfMemoryException
    var bmp=new WriteableBitmap(480800)期间抛出
    我已经将图像大小从1280*768缩小到800*480,我认为这是全屏背景图像的底线,不是吗
  • 经过一些研究,我发现出现这个问题是因为它超过了定期任务的11MB限制
  • 我尝试使用
    DeviceStatus.ApplicationCurrentMemorySage
    跟踪内存使用情况:

    --限制为11534336(位)

    --当后台代理启动时,即使没有任何任务,内存使用量也会变成4648960

    --当从互联网上获得更新时,它增长到了5079040

    --完成后,它下降到4648960

    --当调用开始时(从用户控件生成图像),它增长到8499200

  • 嗯,我想这就是问题所在,它几乎没有可用的内存来通过
    WriteableBitmap
    渲染图像

    你知道怎么解决这个问题吗

    是否有更好的方法从用户控件/或其他任何内容生成图像

    实际上,原始图像可能只有100 kb左右,但是,当使用
    WriteableBitmap
    进行渲染时,文件大小(以及我猜所需的内存大小)可能会增加到1-2MB

    或者我可以从任何地方释放内存吗

    ==============================================================

    顺便说一句,当我在一个周期性任务中只能使用11MB内存时

    然而,这意味着我可以使用高达20 MB或25 MB的WindowsPhone8Update3; 哪个是正确的?为什么我处于第一种情况

    ==============================================================

    编辑:

    谈到调试器,它在

    在调试器下运行时,内存和超时限制将挂起。

    但是为什么我仍然会达到极限呢

    ==============================================================

    编辑:

    嗯,我发现有些东西似乎是有用的,我现在会检查它们,建议仍然是欢迎的

    ==============================================================

    生成图像的代码:

    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, 0, 100);
            }
        }
    }
    
    ImageUserControl
    的XAML代码:

    <UserControl blabla... d:DesignHeight="800" d:DesignWidth="480">
        <Grid x:Name="LayoutRoot">
        <Image x:Name="nBackgroundSource" Stretch="UniformToFill"/>
    
        //blabla...
        </Grid>
    </UserControl>
    
    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
    是存储从internet获取的数据的另一个类时:

    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...
    }
    
    公共类数据信息
    {
    公共字符串Wind1{get{return GetValueOrDefault(“Wind1”,“N/A”);}set{if(AddOrUpdateValue(“Wind1”,value)){Save();}}
    公共字符串Wind2{get{return GetValueOrDefault(“Wind2”,“N/A”);}set{if(AddOrUpdateValue(“Wind2”,value)){Save();}}
    //布拉布拉。。。
    }
    
    如果我对更新进度进行注释,并直接创建图像,它也可以正常工作
    我认为您应该关注这一部分。这似乎表明更新后没有释放某些内存。在渲染图片之前,请确保更新过程中使用的所有引用都超出范围。强制垃圾收集也有助于:

    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect(); // Frees the memory that was used by the finalizers
    

    另外要考虑的是调试器也使用了大量的内存。通过在“发布”模式下编译项目并在手机上部署来进行真正的测试,以确保内存不足

    不过,我已经处于这种情况,所以我知道这可能还不够。要点是:.NETFramework中的一些库是延迟加载的。例如,如果更新过程涉及下载一些数据,则后台代理将加载网络库。无法卸载这些库,这将浪费一些代理的内存。这就是为什么,即使释放更新过程中使用的所有内存,也无法恢复启动后台代理时的可用内存量。看到这一点,我在我的一个应用程序中所做的就是跨越两次执行的后台代理工作负载。基本上,当代理执行时:

    • 如果有待处理的挂起数据,请检入隔离存储。如果没有,只需执行更新过程并将所有需要的数据存储在隔离存储器中
    • 如果存在挂起的数据(即,在下一次执行中),则生成图片并清除数据

    这意味着图片将仅每小时生成一次,而不是每30分钟生成一次,因此只有在其他所有操作都失败时才使用此解决方案。

    较大的内存限制用于后台音频代理,它在文档中明确指出。你被11MB的内存困住了,当你试图在背景中巧妙地处理图片时,这真的是一个很大的痛苦

    480x800为您的内存添加了MB,因为每像素需要4个字节,所以最终大约为1.22MB。当用JPEG压缩时,是的——它的大小只有100KB左右。但无论何时使用WriteableBitmap,它都会加载到内存中

    在forci之前你可以尝试的一件事