Действительно кажется, что использование простого MemoryStream
с AsRandomAccessStream
не работает, хотя я не уверен в причине.Вместо этого вы можете использовать InMemoryRandomAccessStream
, который будет работать должным образом.
Однако существует другая проблема, которая может быть источником проблем или, по крайней мере, приводить к сбою на моем компьютере:
//Render a bitmap image
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal, async () =>
{
await bitmap.RenderAsync(canvas, 1380, 800);
});
Хотя кажется, что await
будет ждать завершения вызова RenderAsync
, этого, к сожалению, нет.Второй параметр - только DispatchedHandler
.Этот делегат имеет следующую подпись:
public delegate void DispatchedHandler()
Как видите, возвращаемое значение Task
отсутствует.Это означает, что он создаст async void
лямбду.Лямбда начнет работать, и когда она достигнет RenderAsync
, она начнет ее выполнять, но await
*1019* может (и, скорее всего, ) закончить до 1024 * делает.Таким образом, вполне вероятно, что вы начнете выполнять bitmap.GetPixelAsync
, пока bitmap
все еще полностью пуст.
Чтобы это исправить, вы должны переместить код внутри лямбды:
//Render a bitmap image
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
await bitmap.RenderAsync(canvas, 1380, 800);
using (var inputImgStream = new InMemoryRandomAccessStream()) //this doesn't work
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId,
inputImgStream
); // I suspect passing the MemoryStream is the issue. While 'StorageFile' is used there are no issues.
IBuffer pixelBuffer = await bitmap.GetPixelsAsync();
Debug.WriteLine($"Capacity = {pixelBuffer.Capacity}, Length={pixelBuffer.Length}");
var pixelArray = pixelBuffer.ToArray();
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint) bitmap.PixelWidth,
(uint) bitmap.PixelHeight,
DisplayInformation.GetForCurrentView().LogicalDpi,
DisplayInformation.GetForCurrentView().LogicalDpi,
pixelArray
);
await encoder.FlushAsync(); // The application hangs here
}
});
Как видите, вы также должны переместить блок using
для потока внутри лямбды, потому что, если бы он был снаружи, случилась бы та же самая судьба - using
мог бы Dispose
потока перед RenderAsync
закончено.