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

本文关键字:异步 何传播 传播 方法 调用 选择 | 更新日期: 2023-09-27 18:09:57

我有几个异步方式编写程序的问题。我正在用一些昂贵的方法编写WCF服务,这些方法是异步调用的好选择。但我对实现的问题是:

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

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

如果我将在模型中创建async方法,那么我需要将服务方法标记为async以便能够等待模型方法,并将返回类型更改为Task。这将破坏服务api约定的一致性。正确的做法是什么?将服务接口设计为异步任务返回方法是否更好,即使有些方法并不昂贵并且实际上没有理由使其async ?

在WCF中,当你改变你的方法来返回一个Task<T>时,你实际上并没有改变WCF契约,因为它可以为单个消息识别多个异步模式,这意味着你可以在单个契约接口中拥有所有3种模式(任务,同步和APM),它们都与同一消息相关。

从MSDN:

客户端可以向开发人员提供他们选择的任何编程模型,因此只要观察到底层消息交换模式。因此,服务可以以任何方式实现操作,只要观察到指定的消息模式

本主题涵盖了以不同形式的WCF服务契约接口进行扩展和异步消费同步WCF服务

根据我的理解,只有开销大的方法应该写成异步的,但是在这种情况下,程序的一半是同步的,另一半是异步的。对吗?

正如@l3arnon所说,暴露async api不是关于该方法有多"昂贵",而是关于该方法调用正在做的工作。如果它是真正的异步工作,例如访问文件系统、发送网络请求、访问外部数据源(例如数据库),那么它是公开异步api的合适候选对象。

将这些事实与WCF相结合,您可以通过单个合约公开同步和异步方法。

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

如果你有很多这样的操作,那么在运行时保持一个线程是一种浪费,而且它会严重阻碍可伸缩性。这是一种权衡,你需要自己决定什么对你更重要:简单性还是可扩展性。

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

  1. 调用者无法检测到您选择的服务方法是同步还是异步。合同不变。无论如何,TaskIAsyncResult都不能通过SOAP序列化,因此不可能将Task传输到客户端。
  2. 不是"昂贵的",而是长时间运行的io绑定。在服务器上使用异步的好处是可以避免线程被阻塞。这个临时节省了1MB的堆栈空间和一个线程池槽。如果您不需要这种增益,而且大多数工作负载都不需要,那么就不要采用异步方式。从开发的角度来看,异步并不是免费的。