ApiController Post 中的异步和等待

Posted

技术标签:

【中文标题】ApiController Post 中的异步和等待【英文标题】:Async and Await in ApiController Post 【发布时间】:2013-10-18 19:57:48 【问题描述】:

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

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

如果我误解了什么,请纠正我。所以,如果上述情况属实,我就会坚持使用我想要异步的 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 对象,因为 await 持有 return Request.CreateResponse(HttpStatusCode.Created, obj); "人质"。

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

【问题讨论】:

【参考方案1】:

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

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

另外,如果 SomeReallyLongRunningTaskAsync() 是 CPU 密集型的,那么你不应该在异步模式下调用它。在服务器场景中使用异步的主要原因将 CLR 线程释放回池,以便 IO 完成端口 (IOCP)可以处理其余的 - 直到 IO 工作完成,然后返回线程池。这样可以避免 ASP.NET 场景中常见的 Thread Starvation 问题。

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

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

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

【讨论】:

【参考方案2】:

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

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

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

正确。

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

没有。 ASP.NET MVC 4.5 看到您返回的是Task&lt;HttpResponseMessage&gt; 而不是HttpResponseMessage,因此在您的Task 完成之前它不会发送响应(在您的async Post 方法结束时)。

【讨论】:

以上是关于ApiController Post 中的异步和等待的主要内容,如果未能解决你的问题,请参考以下文章

将所有 POST 请求路由到单个 ApiController

如何在Web项目中给没有添加API核心组件添加APIController的帮助页HelpPage

转如何在Web项目中给没有添加API核心组件添加APIController的帮助页HelpPage

在 ASP MVC 4 (Beta) 中将 DateTime 发布到 ApiController

内连接和等连接一样吗?

无法从 apicontroller 中的 OwinContext 获取 UserManager