0

I'm saving a RenderTargetBitmap on app's Suspending event. Everything is fine if I have the app opened and I hit "Suspend and shutdown" in Visual Studio. But if I go to Start screen first or open another app and wait a while, in other words - the app isn't in foreground, then RenderTargetBitmap.GetPixelsAsync() method throws this COMException with HResult 0x80004005 and "Unspecified error" description. Considering that in real use suspension happens when user switches from app to something else, this error occurs almost always. The RenderTargetBitmap which I'm saving definetelly isn't null at this point because I do check for that.

Also I have noticed during development, that sometimes when I switch from app to something else and then back, even if the app wasn't suspended and opens instantly, some pictures don't appear in UI as if they have been garbage collected. Which is quite weird, considering that there are still referenced. Not sure if it's related to issue described above, but seems like it could.

Did anyone experience similar issues? What exactly can be happening with those images when app goes off screen?

EDIT:

Here is an example. Xaml:

<Grid x:Name="RootGrid" Background="AntiqueWhite">
    <Rectangle Width="40" Height="50" Fill="Blue"/>
    <Rectangle Width="70" Height="50" Fill="Red" Margin="100 300 0 0"/>
    <Rectangle Width="30" Height="60" Fill="Green"  Margin="0 0 150 70"/>

    <Button x:Name="RenderButton" VerticalAlignment="Top" HorizontalAlignment="Center"
            Margin="0 20 0 0" Content="Render" Click="RenderButton_OnClick"/>
</Grid>

Code behind:

private RenderTargetBitmap renderTargetBitmap;


public MainPage()
{
    InitializeComponent();
    Application.Current.Suspending += CurrentOnSuspending;
}


private async void RenderButton_OnClick(object sender, RoutedEventArgs args)
{
    this.renderTargetBitmap = new RenderTargetBitmap();
    await this.renderTargetBitmap.RenderAsync(RootGrid);
}


private async void CurrentOnSuspending(object sender, SuspendingEventArgs args)
{
    var defferal = args.SuspendingOperation.GetDeferral();

    var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
        "render.png", CreationCollisionOption.ReplaceExisting);
    await SaveToFileAsync(this.renderTargetBitmap, file);

    defferal.Complete();
}


private async Task SaveToFileAsync(RenderTargetBitmap image, IStorageFile file)
{
    using (var stream = await file.OpenStreamForWriteAsync())
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream.AsRandomAccessStream());
        var pixels = await image.GetPixelsAsync();
        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
            (uint)image.PixelWidth, (uint)image.PixelHeight, 96, 96, pixels.ToArray());

        await encoder.FlushAsync();
    }
}

Launch the app on mobile, click "Render" button. After that press Start to put the app off screen, wait a while (10 seconds will do) and press "Suspend and shutdown" in Debug location bar in Visual Studio. Observe COMException.

Andrei Ashikhmin
  • 2,401
  • 2
  • 20
  • 34
  • Could be a bug in your code, but we cannot see it. Please post it, ideally a [mcve]. Related or not, please don't ask two questions in one. The [Ask Question](http://stackoverflow.com/questions/ask) link doesn't wear off when used. – IInspectable Jun 13 '16 at 11:57
  • It doesn't? I was under an impression that you can only ask one question in a lifetime. Thanks for clarifying. I updated the question. – Andrei Ashikhmin Jun 14 '16 at 08:20
  • Does the problem appear when you suspend the application the usual way? Terminating from a debugger isn't something you need to handle, really. – Luaan Jun 14 '16 at 09:07
  • Yes, problem appears in production with hundreds or users. "Suspend and shutdown" isn't simple terminating exactly, it does what is says - first suspending, causing code in Suspending event handler to execute, than shuts the app. You can chose just "Suspend" without shutting down, that would be exactly how it works in production, just put the app off screen first - in real life OS doesn't suspend apps that are in use. – Andrei Ashikhmin Jun 14 '16 at 09:14

0 Answers0