14

我仍然不太清楚 .net 4.5 中的 async 和 await 。到目前为止,我想我理解等待:

  1. 将函数(在其右侧)放在单独的线程上。
  2. 将执行返回给当前函数的调用者
  3. 但保留当前函数的其余代码“人质”,直到等待(异步)函数完成。

如果我误解了什么,请纠正我。所以,如果上述情况属实,我就会坚持使用我想要异步的 ApiController 的 Post 函数:

[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody]MyObject obj)
{        
     myDataContext.MyObjects.InsertOnSubmit(obj);
     myDataContext.SubmitChanges();

     await SomeReallyLongRunningTaskAsync();        

     // obj would now have the new Id, which I'm really after.
     return Request.CreateResponse(HttpStatusCode.Created, obj);

}

因此,如果我正确理解这一点,Post 将完成执行并将控制权返回给调用myApiController.Post(obj). 但我还没有HttpResponseMessage对象,因为等待被return Request.CreateResponse(HttpStatusCode.Created, obj);“人质”。

在上面这个简单的例子中,调用是否会立即返回到客户端(即客户端 JS 网站或移动应用程序)?如果是这样,它会是 201、400、500(最好不要),还是其他?

4

2 回答 2

27

除了斯蒂芬的回答,我还需要指出一些事情。

首先,控制器中的异步不会使用户体验异步。只要SomeReallyLongRunningTaskAsync()需要,用户就必须等待。[那我们为什么要异步?看下一点]

此外,如果它受SomeReallyLongRunningTaskAsync()CPU 限制,则不应在异步模式下调用它。在服务器场景中使用异步的主要原因是将CLR线程释放回池中,以便IO 完成端口 (IOCP)可以处理其余部分 - 直到 IO 工作完成,然后返回线程池。这将防止ASP.NET 场景中常见的线程饥饿问题。

IOCPIO 绑定的情况下使用,示例如下:

  • 读取/写入文件
  • 访问数据库或
  • 访问外部 Web 服务或 WCF 服务

网上有大量可用资源,并解释了各个方面。如果我可以插上一句,本书的第 2 章是一个很好的资源,它提供了对 Web API 中异步的内聚理解。

于 2013-10-11T08:08:05.640 回答
15

将函数(在其右侧)放在单独的线程上。

async,不会启动新线程。我有一个async介绍,你可能会觉得有帮助。

Post 将完成执行并将控制权返回给调用 myApiController.Post(obj) 的任何人。但我还没有 HttpResponseMessage 对象

正确的。

在上面这个简单的例子中,调用是否会立即返回到客户端(即客户端 JS 网站或移动应用程序)?

不。ASP.NET MVC 4.5 看到您正在返回Task<HttpResponseMessage>而不是HttpResponseMessage,因此它不会发送响应,直到您Task完成(在您的async Post方法结束时)。

于 2013-10-10T22:00:30.040 回答