如果方法已经异步,我应该进行快速操作异步

时间:2016-06-30 08:42:15

标签: c# asynchronous async-await

我有这个代码(不重要的细节是它在AWS中的EC2实例上运行,处理SQS队列上的消息)。

方法中的第一个语句通过http获取一些数据,第二个语句将状态保存到本地dynamo数据存储。

public bool HandleMessage(OrderAcceptedMessage message)
{
    var order = _orderHttpClient.GetById(message.OrderId);
    _localDynamoRepo.SaveAcceptedOrder(message, order);
    return true;
}

性能特征是http往返行程需要100-200毫秒,而发电机写入大约需要10毫秒。

这两个操作都有async个版本。我们可以写如下:

public async Task<bool> HandleMessage(OrderAcceptedMessage message)
{
    var order = await _orderHttpClient.GetByIdAsync(message.OrderId);
    await _localDynamoRepo.SaveAcceptedOrderAsync(message, order);
    return true;
}

所以指导是因为第一次操作&#34;可能需要超过50毫秒来执行&#34;它应该使用async和await。 (1)

但是第二次快速操作呢?这两个论点中的哪一个是正确的:

不要让它异步:它不符合50ms标准,并且不值得花费。

确保异步:上一次操作已经支付了开销。已经有基于任务的异步发生,值得使用它。

1)http://blog.stephencleary.com/2013/04/ui-guidelines-for-async.html

4 个答案:

答案 0 :(得分:6)

  

不重要的细节是它在AWS中的EC2实例上运行,处理SQS队列上的消息

实际上,我认为这是一个重要的细节。因为这不是UI应用程序;它是一个服务器应用程序。

  

指导是因为第一次操作&#34;可能需要超过50毫秒来执行&#34;

本指南仅适用于UI应用程序。因此,50ms准则在这里毫无意义。

  

这两个论点中的哪一个是正确的

异步与速度无关。它是关于释放线程的。 UI应用程序的50ms准则就是释放UI线程。在服务器端,async是关于释放线程池线程的。

问题是您想要/需要多少可扩展性?如果你的后端是可扩展的,那么我通常会推荐async,因为这会释放线程池线程。这使您的Web应用程序更具可扩展性,并且能够更快地响应负载变化。但是,如果您的后端可以与您的网络应用程序一起扩展,这只会给您带来好处。

答案 1 :(得分:1)

首先请注意,在网络应用中,异步的最大成本是降低生产力。这就是我们正在权衡的好处。如果将这一方法设为异步,则需要考虑将会感染多少代码。

好处是在通话期间保存一个线程。一个200ms的HTTP调用对异步来说是一个非常好的例子(虽然不可能肯定地说,因为它还取决于你执行调用的频率)。

50ms标准不是硬数。实际上,该建议适用于实时UI应用程序。

更有用的数字是latency times frequency。这告诉你长期平均消耗了多少线程。不经常调用不需要优化。

在一个线程被阻止的情况下,每秒10毫秒的100个发电机呼叫出现。这不重要。所以这可能不是异步的好选择。

当然,如果您进行第一次异步调用,您可以使第二次调用异步,几乎没有增加的生产力成本,因为所有内容都已被感染。

您可以自己运行这些数字并根据该数据来决定。

答案 2 :(得分:1)

这可能最终会在一场自以为是的讨论中结束......但我们试试吧。 tl; dr:是的,保持异步。

您在库中并且不关心同步上下文,因此您不应该捕获它并将代码更改为:

var order = await _orderHttpClient.GetByIdAsync(message.OrderId).ConfigureAwait(false);
await _localDynamoRepo.SaveAcceptedOrderAsync(message, order).ConfigureAwait(false);

此外:在第一次await ed调用之后,您可能最终会遇到线程池的一个线程。因此,即使您使用非异步版本SaveAcceptedOrder(),它也不会阻止。但是,这不是你应该依赖的你不一定知道异步方法的类型(CPU绑定或IO绑定=“async by design”)。如果它是IO绑定的,则不需要在线程上运行它。

答案 3 :(得分:1)

如果您正在进行任何远程呼叫,请将其设为异步。是的,DynamoDB调用速度很快(除非其中一个具有低于标准的哈希键,或者单个表中有数千兆字节的数据),但您仍然通过互联网进行(即使你在AWS EC2等内部,所以你不应该忽略任何Eight Fallacies of Distributed Computing - 尤其不是1)网络可靠或2)延迟为零。