如何选择C#中的异步调用方法,如何传播异步调用。

4

我有几个关于编写异步程序的问题。我正在编写一些昂贵方法的WCF服务,这些方法非常适合进行异步调用。但是我的问题是:

  1. 如果我在模型中创建异步方法,则需要将服务方法标记为异步才能等待模型方法,并将返回类型更改为Task<originalType>。这会破坏服务API约定的一致性。正确的方法是什么?即使某些方法不昂贵并且实际上没有理由使其异步,是否更好地将服务接口设计为返回async Task的方法?
  2. 据我所了解,只有昂贵的方法应该编写为异步方法,但在这种情况下,程序的一半将是同步的,另一半将是异步的。这是正确的吗?
3个回答

5

当存在“昂贵”的方法时,我不会说你需要使用async-await。更好的指导原则是在存在真正异步操作(主要是IO调用)时使用async-await

如果你有许多这样的操作,持续占据线程将是一种浪费,并且可能会严重阻碍可扩展性。这是一种权衡,你需要自己决定什么对你更重要:简单性还是可扩展性。

如果你的应用程序是一个富客户端,也许可扩展性并不是那么重要,但在WCF服务中,如果可以的话,我总是选择异步选项。


1
在GUI应用程序中,您不希望阻塞UI线程以进行长时间运行的同步(例如CPU绑定)操作,因此最好在那里使用类似于await Task.Run()的东西。但是对于WCF服务或类似服务,情况并非如此。 - svick
1
@svick 确实如此。WCF服务中的async-await是关于可扩展性的,而在GUI应用程序中则关乎卸载。 - i3arnon

5
如果我在模型中创建异步方法,那么我需要将服务方法标记为async以便能够等待模型方法,并将返回类型更改为Task。这将破坏服务API的一致性约定。正确的方法是什么?即使某些方法不昂贵且实际上没有理由使其成为异步,是否最好将服务接口设计为异步任务返回方法?在WCF中,当您将方法更改为返回Task<T>时,实际上并未更改WCF合同,因为它可以为单个消息识别多个异步模式,这意味着您可以在单个合同接口中拥有所有3种模式(任务、同步和APM),它们都与同一消息相关联。来自MSDN的信息:客户端可以提供任何他们选择的编程模型,只要遵守底层的消息交换模式即可。同样,服务也可以以任何方式实现操作,只要遵守指定的消息模式即可。
这个主题涉及到扩展WCF服务契约接口的不同形式异步消费同步的WCF服务
正如@l3arnon所说,公开一个async API并不是关于方法有多“昂贵”,而是关于方法调用所做的工作。如果它是真正的异步工作,比如访问文件系统、发送网络请求、访问外部数据源(例如数据库),那么这就是公开async API的合适候选者。
结合WCF,您可以通过单个契约公开同步和异步方法。

被选为最佳答案,但所有答案都非常有用。谢谢大家。 - Fanda

2
  • 调用者无法检测您选择的服务方法是同步还是异步。契约不会改变。因为TaskIAsyncResult在SOAP上不可序列化,所以不可能将Task传输到客户端。我之前已经详细解释过这个问题。
  • 不是“昂贵”,而是长时间运行的IO绑定操作。在服务器上使用异步的好处是可以避免线程被阻塞。这样可以暂时节省1MB的堆栈空间和一个线程池插槽。如果您不需要这种优势(大多数工作负载都不需要),请不要使用异步。从开发角度来看,使用异步并非免费。

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