Приложение WinRT зависает при вызове BitmapDecoder.CreateAsync(stream)

У меня есть следующий метод, в котором я передаю InMemoryRandomAccessStream, загруженный данными JPEG:

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

Этот метод зависает все время, за исключением случаев, когда я ставлю точку останова на первую строку и перехожу через каждую строку. Я пытался использовать разные изображения JPEG, изменять параметры «GetPixelDataAsync» и временно вставлять «ожидание Task.Delay (...)» между строками, но ничего не помогает. Приложение выполняет множество других трудоемких асинхронных операций и работает нормально, за исключением этой части. Непонятно, почему установка точки останова (за исключением того, что она дает некоторую временную задержку) заставляет ее работать.

Пожалуйста, помогите решить эту проблему.


person Victor    schedule 20.09.2012    source источник
comment
не могли бы вы показать, как вы вызываете этот метод?   -  person Manuel Rauber    schedule 23.09.2012


Ответы (1)


Я думаю, в дикой природе, но у меня была та же проблема.

Я думаю, вы вызываете этот асинхронный метод из контекста синхронизации, например:

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

Это приведет к тому, что ваше приложение будет работать в потоке пользовательского интерфейса, что приведет к взаимоблокировке. Либо сделайте вызывающий метод асинхронным, что будет работать, либо используйте 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();
}

Может быть, взгляните здесь на это очень хорошее объяснение использования async/await и получения взаимоблокировок.

person Manuel Rauber    schedule 23.09.2012
comment
Вместо этого я выбрал подход WritableBitmap. Тем не менее, проблема взаимоблокировки пользовательского интерфейса в целом с ConfigureAwait(false) кажется разумным решением. Спасибо, Рауби! - person Victor; 26.09.2012
comment
Не работает для меня. Все еще висит с оригинальным сценарием OP. - person Quarkly; 28.04.2014
comment
ссылка explanation больше не работает. Кто знает где взять новую ссылку. Или, что еще лучше, поместить объяснение как часть ответа? - person user1; 19.07.2017