Async await与GetAwaiter().GetResult()以及回调的区别

49
我正在尝试找到我的一个项目的最佳实践。这是一个典型的WPF应用程序,具有显示项目列表的UI,还有一个返回结果的数据服务。
我们异步调用服务以避免阻塞UI。我们面前有两个选择:
1. 使用Async await关键字 这需要从按钮单击到服务层(在客户端上进行http调用的类)以及之间任何方法都标记为Async。这种方法除了传播异步存在问题外,其他方面都可以正常工作。
2. 使用awaiter和回调 在这种方法中,UI客户端调用服务层并将回调传递给服务层,服务层将服务器上的http调用包装在任务中,并使用GetAwaiter().GetResult(),当http调用完成时,它会调用UI客户端传递的回调。在这种情况下,不必标记任何方法为async,但对于GetAwaiter()的使用还不确定。
Task.Run(async () => //等待http调用,调用回调).GetAwaiter().GetResult();
我只是想找出哪种方法更好,并且是否存在任何问题,我应该注意些什么。

2
我非常确定第二种方法有时可能会导致死锁。我知道这是因为我在使用Windows Universal进行开发时遇到了类似的情况。 - Felype
还有一个问题是异常处理。我知道在完全异步的实现中,你会在最后收到AggregateException,但是我不知道GetAwaiter方法中发生的异常该怎么处理。 - Eris
@Eris 当你使用await时,你不会得到一个“AggregateException”。你会得到内部异常。使用“GetResult”也是同样的情况。 - i3arnon
1个回答

62

您应该一直使用asyncawait关键字,或者干脆不使用async

第二个选项并不是真正的异步。 它调用了一个异步操作,并使用task.GetAwaiter().GetResult()在同步阻塞上。除了非常复杂之外,它也不是异步的,可能会导致死锁。


4
你有更多关于为什么会导致死锁的背景信息吗?我也遇到过这个问题,但我想要更深入的信息,了解为什么会发生这种情况或者它是如何运作的。 - Frederik Gheysels
7
好的,请提供需要翻译的语言。 - i3arnon
3
那么,如果不使用async,如何调用像FileIO.ReadBufferAsync这样的函数呢? - Quark Soup
2
@TheWebGuy 不确定你在问什么。但是,如果任务出错,awaitGetAwaiter().GetResult() 都会重新抛出异常。 - i3arnon
4
async 关键字出现之前,已经存在异步编程的方法。你可以使用 Task.ContinueWith 并提供回调函数,就像在 JavaScript 中普遍使用的那样。本质上是一样的。asyncawait 只是让编程更加简便。 - Emperor Eto
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接