Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该将wait与异步操作方法一起使用吗?_C#_Asp.net Mvc_Multithreading_Asynchronous_Async Await - Fatal编程技术网

C# 我应该将wait与异步操作方法一起使用吗?

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() { //执行长时间运行的调用。 返回视图(); }

我需要在控制器中为长时间运行的外部API调用实现异步操作

查看一些教程,我实现了如下方法:

    [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();
    }