MVC4 + async/await + 动作完成前返回响应 [英] MVC4 + async/await + return response before action completes

查看:31
本文介绍了MVC4 + async/await + 动作完成前返回响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 MVC4 应用程序中,我需要添加一个控制器来上传和处理大文件.文件上传后,我需要立即开始对该文件的异步处理并将响应返回给浏览器,而无需等待处理完成.

In my MVC4 app I need to add a controller for uploading and processing large files. Immediately after the file is uploaded I need to start async processing of that file and return response to the browser without waiting for the processing to complete.

显然我可以启动一个新线程来手动处理文件,但我想知道我是否可以使用 .net 4.5 引入的 async/await 机制来实现这个场景

Obviously I could start a new thread for processing the file manually, but I'm wondering if I can implement this scenario using async/await mechanism introduced with .net 4.5

为了测试这个概念,我尝试过这样的事情:

To test the concept I've tried something like this:

public async Task<ActionResult> Test()
{
    TestAsync();
    return View("Test");
}

public async void TestAsync()
{
    await LongRunning();
}

private Task<int> LongRunning()
{
    return Task<int>.Factory.StartNew(() => Pause());
}

private int Pause()
{
    Thread.Sleep(10000);
    return 3;
}

异步机制似乎一般有效:当我调试代码时,我点击了返回视图(测试");"返回 3"行之前的行.但是,浏览器只有在 Pause 方法完成后才会收到响应.

The async mechanism seems to work in general: when I debug the code I hit the "return View("Test");" line before the line "return 3". However, the browser receives the response only after the Pause method completes.

这似乎表现得像常规的异步控制器(具有 Async 和 Completed 方法的控制器).有没有办法在我的场景的控制器中使用 async/await?

This seems to behave like regular async controllers (the ones with Async and Completed methods). Is there a way to use async/await in controllers for my scenario?

推荐答案

显然我可以启动一个新线程来手动处理文件,但我想知道我是否可以使用 .net 4.5 引入的 async/await 机制来实现这个场景

Obviously I could start a new thread for processing the file manually, but I'm wondering if I can implement this scenario using async/await mechanism introduced with .net 4.5

不,你不能,因为 async 不会改变 HTTP 协议.

No, you cannot, because async doesn't change the HTTP protocol.

Svick 和 James 已经将正确答案作为评论发布,为方便起见,我在下面复制:

Svick and James have already posted the correct answers as comments, which I duplicate below for convenience:

IIS 几乎可以随时回收您的应用程序.

IIS can recycle your application pretty much at any time.

如果您有长时间运行的事情要异步执行请求,请在其他地方执行.典型"是一个持久队列(MSMQ、Azure、RabbitMQ 等)和其他东西(Windows 服务、由任务调度程序运行的 exe、使用 Quartz.net 的应用程序等)处理它们.

If you have long-running things to do async to the request, do them elsewhere. The 'typical' is a persistent queue (MSMQ, Azure, RabbitMQ, etc) with something else (windows service, exe run by task scheduler, app using Quartz.net, etc) processing them.

总而言之,HTTP 为您提供一个请求和一个响应(async - 以及其他任何东西 - 都不会改变这一点).

To summarize, HTTP gives you one request and one response (async - and anything else - won't change this).

ASP.NET 是围绕 HTTP 请求设计的(并假设如果没有未完成的请求,则停止该网站是安全的").您可以启动一个新线程并将上传的内容保存在内存中(这是最简单的方法),但强烈不建议这样做.

ASP.NET is designed around HTTP requests (and makes assumptions like "if there are no outstanding requests, then it's safe to stop this web site"). You can kick off a new thread and keep your upload in memory (which is the easiest way to do it), but it's strongly not recommended.

对于您的情况,我建议您遵循 James 的建议:

For your situation, I recommend you follow James' suggestion:

  • 上传完成后,将上传内容保存到持久存储(例如 Azure 队列),然后返回一张票".到浏览器.
  • 让其他进程(例如 Azure 辅助角色)处理队列,最终将其标记为完成.
  • 让浏览器用它的票"轮询服务器.服务器使用票"在持久存储中查找文件并返回它是否完整.

对此有一些变化(例如,在处理完成时使用 SignalR 通知浏览器),但总体架构是相同的.

There are some variations to this (e.g., using SignalR to notify the browser when processing is complete), but the general architecture is the same.

这很复杂,但这是正确的做法.

This is complex, but it's the right way to do it.

这篇关于MVC4 + async/await + 动作完成前返回响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆