我正在使用uwp应用程序中的RenderTargetBitmap将UIelement转换为流。但是我不知道如何让线程等到流的转换。我尝试使用建议,但是找不到合适的解决方案。非常感谢您的帮助。
{
for (int count = 0; count <= Textpage.Children.Count; count++)
{
if (Textpage.Children[count] is Viewbox)
{
CustomView customView = (Textpage.Children[count] as Viewbox).Child as CustomView;
UIElement frameworkElement = customView as UIElement;
(Textpage.Children[count] as Viewbox).Child = null;
var element = (PdfDocumentPanel.Children[count] as Border).Child as Canvas;
Textpage.Children.Remove((Textpage.Children[count] as Viewbox));
SaveCustomAnnotation(frameworkElement, pageIndex, documentToBeSaved);
}
}
}
Stream savedStream = new MemoryStream();
}
internal async void SaveCustomAnnotation(UIElement element, int pageIndex, PdfLoadedDocument loadedDocument)
{
Type pageChild = null;
IRandomAccessStream randomStream;
randomStream = await Task.Run(() => ConvertToImage(element));
}
public async Task<IRandomAccessStream> ConvertToImage(UIElement element)
{
InMemoryRandomAccessStream randomAccessStream = null;
IBuffer pixelBuffer = null;
RenderTargetBitmap bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(element);
pixelBuffer = await bitmap.GetPixelsAsync();
var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
using (randomAccessStream = new InMemoryRandomAccessStream())
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, randomAccessStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)bitmap.PixelWidth,
(uint)bitmap.PixelHeight,
logicalDpi,
logicalDpi,
pixelBuffer.ToArray());
await encoder.FlushAsync();
}
return randomAccessStream;
}
我希望在完成初始化新的内存流之前完全完成SaveCustomannotation方法
答案 0 :(得分:8)
问题出在这里是async void
的滥用,这阻止了您等待。入门时的一个好规则是,如果您输入单词async void
停止...从计算机上退后一步,然后告诉自己,可能还有更好的方法...应该主要使用它们用于事件处理程序。
基本上SaveCustomAnnotation
应该返回Task
internal async Task SaveCustomAnnotation(UIElement element, int pageIndex, PdfLoadedDocument loadedDocument)
然后您需要await
await SaveCustomAnnotation(frameworkElement, pageIndex, documentToBeSaved);
这样,它的调用方法也应该是async Task
(一直到调用链的整个末端),只有这样,它们的调用方法才应该是async void
,并且必须是事件处理程序。
最后一个提示
Async void
方法具有不同的错误处理语义。如果从async Task
或async Task<T>
方法抛出异常,则捕获该异常并将其放置在Task
上。使用async void
方法时,没有Task对象(它们是不可观察的),因此从async void
方法抛出的任何异常都将直接在启动时处于活动状态的SynchronizationContext上引发。
简而言之,总是使用此类方法捕获并处理来自其中的异常
(正确的说)Jonathon Chase一样。
如果这是全部操作,您可能应该只从main方法调用它并等待它,因为它无论如何都会返回任务并标记为
internal async void SaveCustomAnnotation(UIElement element, int pageIndex, PdfLoadedDocument loadedDocument)
{
Type pageChild = null;
IRandomAccessStream randomStream;
randomStream = await Task.Run(() => ConvertToImage(element));
}
您可以删除整个方法,而只需替换
await SaveCustomAnnotation(frameworkElement, pageIndex, documentToBeSaved);
与
var readstream = await ConvertToImage(frameworkElement);
有关此代码的还有 iffy ,但是我认为它们应该属于另一个问题