OutOfMemoryException @ WriteableBitmap @ background agent

Viewed 1103

I have a Windows Phone 8 App, which uses Background agent to:

  1. Get data from internet;
  2. Generate image based on a User Control that uses the data from step 1 as data source;
  3. In the User Control I have Grid & StackPanel & some Text and Image controls;
  4. When some of the Images use local resources from the installation folder (/Assets/images/...) One of them which I used as a background is selected by user from the phone's photo library, so I have to set the source using C# code behind.

However, when it runs under the background, it get the OutOfMemoryException, some troubleshooting so far:

  1. When I run the process in the "front", everything works fine;
  2. If I comment out the update progress, and create the image directly, it also works fine;
  3. If I don't set the background image, it also works fine;
  4. The OutOfMemoryException was thrown out during var bmp = new WriteableBitmap(480, 800);
    I already shrink the image size from 1280*768 to 800*480, I think it is the bottom line for a full screen background image, isn't it?
  5. After some research, I found out this problem occurs because it exceeded the 11 MB limitation for a Periodic Task.
  6. I tried use the DeviceStatus.ApplicationCurrentMemoryUsage to track the memory usage:

    -- the limitation is 11,534,336 (bit)

    -- when background agent started, even without any task in it, the memory usage turns to be 4,648,960

    -- When get update from internet, it grew up to 5,079,040

    -- when finished, it dropped back to 4,648,960

    -- When the invoke started (to generate image from the User Control), it grew up to 8,499,200

Well, I guess that's the problem, there is little memory available for it to render the image via WriteableBitmap.

Any idea how to work out this problem?

Is there a better method to generate an image from a User Control / or anything else?

Actually the original image might only be 100 kb or around, however, when rendering by WriteableBitmap, the file size (as well as the required memory size I guess) might grew up to 1-2MB.

Or can I release the memory from anywhere?

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

BTW, when this Code Project article says I can use only 11MB memory in a Periodic Task;

However, this MSDN article says that I can use up to 20 MB or 25MB with Windows Phone 8 Update 3; Which is correct? And why am I in the first situation?

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

Edit:

Speak of the debugger, it also stated in the MSDN article:

When running under the debugger, memory and timeout restrictions are suspended.

But why would I still hit the limitation?

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

Edit:

Well, I found something seems to be helpful, I will check on them for now, suggestions are still welcome.

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/

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

The code to generate the image:

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);
        }
    }
}

The XAML code for the ImageUserControl:

<UserControl blabla... d:DesignHeight="800" d:DesignWidth="480">
    <Grid x:Name="LayoutRoot">
    <Image x:Name="nBackgroundSource" Stretch="UniformToFill"/>

    //blabla...
    </Grid>
</UserControl>

The C# code behind the ImageUserControl:

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) { }
}

When DataInfo is another Class within the settings page that hold data get from the 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...
}
2 Answers
Related