Search code examples
c#windows-runtimewinrt-async

WinRT App hangs when BitmapDecoder.CreateAsync(stream) is called


I have the following method where I pass a InMemoryRandomAccessStream loaded with JPEG data:

private async Task<byte[]> GetDataAsync(IRandomAccessStream stream)
{
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);

    BitmapFrame frame = await decoder.GetFrameAsync(0);

    BitmapTransform transform = new BitmapTransform()
    {
        ScaledWidth = decoder.PixelWidth,
        ScaledHeight = decoder.PixelHeight
    };

    PixelDataProvider pixelData = await frame.GetPixelDataAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, transform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);

    return pixelData.DetachPixelData();
}

This method hangs all the time except if I put a breakpoint to the first line and step over each line. I tried to use different JPEG images, modify the parameters of "GetPixelDataAsync" and temporary insert "await Task.Delay(...)" between lines, but nothing helps. The App performs a lot of other time consuming asynchronous operations and works fine except for this part. It is unclear why setting a breakpoint (except that it gives some time delay) makes it work.

Please help to solve this problem.


Solution

  • I guess in the wild, but I had the same problem.

    I think you call this async method from a sync context like:

    private void ButtonClick(...) 
    {
      var bytes = GetDataAsync(...);
    }
    

    This will cause your application to run in the UI Thread which causes a deadlock. Either make the calling method async, too, which will work or use ConfigureAwait(false):

    private async Task<byte[]> GetDataAsync(IRandomAccessStream stream)
    {
        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream).AsTask().ConfigureAwait(false);
    
        BitmapFrame frame = await decoder.GetFrameAsync(0).AsTask().ConfigureAwait(false);
    
        BitmapTransform transform = new BitmapTransform()
        {
            ScaledWidth = decoder.PixelWidth,
            ScaledHeight = decoder.PixelHeight
        };
    
        PixelDataProvider pixelData = await frame.GetPixelDataAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, transform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage).AsTask().ConfigureAwait(false);
    
        return pixelData.DetachPixelData();
    }
    

    Maybe take a look here at this very nice explanation of using async/await and getting deadlocks.