如何在C#中等待异步任务完成?
我正在使用uwp应用程序中的RenderTargetBitmap将UIelement转换为流。但是我不知道如何让线程等待流的转换。我曾尝试采用这些建议,但未能找到合适的解决办法。非常感谢您的帮助如何在C#中等待异步任务完成?,c#,async-await,C#,Async Await,我正在使用uwp应用程序中的RenderTargetBitmap将UIelement转换为流。但是我不知道如何让线程等待流的转换。我曾尝试采用这些建议,但未能找到合适的解决办法。非常感谢您的帮助 { for (int count = 0; count <= Textpage.Children.Count; count++) { if (Textpage.Children[count] is Viewbox) {
{
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;
}
{
对于(int count=0;count ConvertToImage(元素));
}
公共异步任务转换图像(UIElement)
{
InMemoryRandomAccessStream randomAccessStream=null;
IBuffer pixelBuffer=null;
RenderTargetBitmap位图=新建RenderTargetBitmap();
等待位图.RenderAsync(元素);
pixelBuffer=等待位图。GetPixelsAsync();
var logicalDpi=DisplayInformation.GetForCurrentView().logicalDpi;
使用(randomAccessStream=new InMemoryRandomAccessStream())
{
var encoder=等待BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId,randomAccessStream);
编码器.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode。忽略,
(uint)bitmap.PixelWidth,
(uint)bitmap.PixelHeight,
logicalDpi,
logicalDpi,
pixelBuffer.ToArray());
等待编码器。FlushAsync();
}
返回随机数据流;
}
我希望在移动初始化新内存流之前完全完成SaveCustomannotation方法这里的问题是误用了
异步void
,这使您无法等待它。开始时的一个好规则是,如果键入单词async void
stop。。。从你的电脑前退一步,告诉你自己可能有更好的方法。。。它们应该主要用于事件处理程序
基本上,SaveCustomAnnotation
应该返回一个Task
internal async Task SaveCustomAnnotation(UIElement element, int pageIndex, PdfLoadedDocument loadedDocument)
然后你需要等待它
await SaveCustomAnnotation(frameworkElement, pageIndex, documentToBeSaved);
因此,它的调用方法也应该是async Task
(一直到调用链的上游),只有这样,它们的调用方法才应该是async void
,并且只有当它是一个事件处理程序时
最后一个音符
Async void
方法具有不同的错误处理语义。当从异步任务
或异步任务
方法中抛出异常时,将捕获该异常并将其放置在任务
中。使用async void
方法时,没有任务对象(它们在未观察到的情况下运行),因此从async void
方法抛出的任何异常将直接在启动时处于活动状态的SynchronizationContext上引发
简而言之,在这些方法中始终捕获并处理来自的异常
正如所逃避的那样(这是正确的) 如果这就是它所做的一切,您可能应该从main方法调用它并等待它,因为它仍然返回一个任务并标记为async
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);
与
关于这段代码还有很多不确定的地方,但我认为它们可能属于另一个相关问题:。Async void与Async void大不相同,不仅因为它不能等待,而且因为Async void方法中任何未经处理的异常都可能导致程序崩溃。另请参阅,其中包含有关C#Async
/await
功能的详细信息。你几乎不是第一个就不能等待async void
方法提出问题的人。@Jonathon:“我们将看到的有很多不同的变体”--将其归入同一类NullReferenceException
。我可能有点简短,但事实是,人们在没有做任何真正的研究的情况下发布了这类问题。每一篇讨论C#异步
/等待
功能的合理参考文献,包括微软自己的文档、大量关于堆栈溢出的文章(包括我提供链接的事实上的规范性文章),以及各种专家的博客文章,都解释了异步无效
的危害。这是最基本的。
var readstream = await ConvertToImage(frameworkElement);