C# 我应该将wait与异步操作方法一起使用吗?
我需要在控制器中为长时间运行的外部API调用实现异步操作 查看一些教程,我实现了如下方法:C# 我应该将wait与异步操作方法一起使用吗?,c#,asp.net-mvc,multithreading,asynchronous,async-await,C#,Asp.net Mvc,Multithreading,Asynchronous,Async Await,我需要在控制器中为长时间运行的外部API调用实现异步操作 查看一些教程,我实现了如下方法: [AsyncTimeout(200)] public async Task<ActionResult> DoAsync() { // Execute long running call. return View(); } [异步超时(200)] 公共异步任务DoAsync() { //执行长时间运行的调用。 返回视图(); }
[AsyncTimeout(200)]
public async Task<ActionResult> DoAsync()
{
// Execute long running call.
return View();
}
[异步超时(200)]
公共异步任务DoAsync()
{
//执行长时间运行的调用。
返回视图();
}
我的问题是,这是否足以使它真正成为非块异步的?我还需要应用wait操作符吗?如果需要,我应该如何做?要编写非阻塞异步代码,需要执行某种现有的非阻塞异步操作,例如
Task.Delay()
,或异步网络或文件IO
简而言之,wait
关键字使用异步;它不创造它
如果您没有任何实际的异步工作要做,
await
对您没有任何好处。正如另一个人所写,您需要一个异步操作来等待它,以使View()
异步地将它包装在
[异步超时(200)]
公共异步任务DoAsync()
{
//执行长时间运行的调用。
返回等待任务。运行(()=>View());
}
之后,此方法主要用于从其他异步函数或回调调用
我需要在控制器中为长时间运行的外部API调用实现异步操作…
我的问题是,这是否足以使它真正成为非块异步的?我是否还需要应用等待运算符,如果需要,我应该如何操作 C#编译器可能已经暗示
async
关键字在这里是多余的:
[AsyncTimeout(200)]
public async Task<ActionResult> DoAsync()
{
// Execute long running call.
return View();
}
[异步超时(200)]
公共异步任务,您仍然无法突破给定HTTP请求的边界。生成视图所需的时间至少与不生成任务所需的时间相同。运行。客户端浏览器仍将等待它
当您需要将CPU绑定的工作卸载到池线程时,此模式适用于UI应用程序,以避免阻塞UI线程并保持UI响应。然而,在ASP.NET应用程序中的HTTP请求处理程序中使用它几乎从来都不是一个好主意。这只会损害性能和可伸缩性
一种解决方案是运行跨越单个HTTP请求边界的后台任务,为视图
花费大量时间编写时提供用户友好的体验。然后进一步使用AJAX请求保持客户端浏览器随着进度而更新。下面是Alan D.Jackson的一个很好的例子:
但是,在同一ASP.NET服务器进程内跨多个HTTP请求运行冗长的后台操作不是一个好主意。虽然它相对容易实现,但这种方法可能会在IIS的可维护性、可伸缩性和安全性方面产生问题
您最好使用一个单独的API,它将公开一个基于任务的API。然后使用AJAX定期轮询WCF服务,使用ASP.NET MVC控制器的专用方法作为轮询调用的代理
我的问题是,这是否足以使它真正成为非块异步的?我是否还需要应用等待运算符,如果需要,我应该如何操作
您应该在异步MVC操作中使用wait
关键字,原因如下:
如果您的操作更改了应用程序的状态(更新数据库等),则await
关键字可以在外部服务失败时回滚更改。否则,这可能会导致状态不一致,因为用户不能只回放给定的异步操作,它只能回放整个操作
托管环境(IIS)可能导致应用程序域卸载,原因是。发生这种情况时,应用程序可能永远不会获得异步操作的结果。在常规请求处理情况下,ASP.NET会等待每个操作完成。如果某些请求的完成时间过长(并超过关机超时),ASP.NET将中止这些请求并发送失败响应
这就是为什么您既不应该使用不带wait的async
,也不应该使用其他.NET异步技术(如TPL)的原因。在这种情况下,带有WCF的自定义Windows服务是一个更好的解决方案,但它会使编程、部署和维护任务变得非常复杂
当然,您可以使用,这是。但是,当ASP.NET调用接口实现的Stop
方法(在关闭期间)时,您只有30秒(默认情况下)来保存数据。如果有未完成的异步操作,则应中止这些操作,将其标记为失败,并在重新启动后重试,或向用户发送失败通知。如果此时您的存储也不可用,请对您的结果(包括失败的结果)说再见
您还可以在ASP.NET应用程序中使用持久队列、可靠的抓取和侦听这些队列的专用工作程序。这甚至可以保护您不受工作进程终止的影响。此外,还有很多项目,如、、等,但它们是针对其他语言的
对于.NET,请试一试——它仍在开发中,但比这类系统的初始实现稳定得多,并且具有许多不同的功能。那么这如何适用于调用可能需要一段时间的API呢?它会一直等到完成吗?@shenku,ASP.NET引擎确实会等待,然后将视图作为HTTP请求的一部分返回。但是客户端浏览器可能会决定不等待并同时超时请求。在ASP.NET中执行return wait Task.Run(()=>View())
没有意义,它不是UI应用程序。这背后的原因是什么?在完成此任务之前,HTTP响应不会发送到客户端。您仍在使用线程执行任务。那么,为什么不干脆re呢
[AsyncTimeout(200)]
public async Task<ActionResult> DoAsync()
{
// Execute long running call.
return View();
}