MVC4 +异步/伺机+返回响应操作完成之前 [英] MVC4 + async/await + return response before action completes

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

问题描述

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

很显然,我可以开始一个新的线程手动处理文件,但我不知道我是否可以使用异步实现这个场景/等待着引进机制。NET 4.5

要测试我已经试过像这样的概念:

 公共异步任务<&的ActionResult GT;测试()
{
    TestAsync();
    返回视图(测试);
}公共异步无效TestAsync()
{
    等待LongRunning();
}私人任务< INT> LongRunning()
{
    返回任务< INT> .Factory.StartNew(()=>暂停());
}私人诠释暂停()
{
    Thread.sleep代码(10000);
    返回3;
}

异步机制似乎在一般的工作:当我调试code我打的返回视图(测试);行返回3前行。然而,浏览器接收该暂停方法完成之后,才响应。

这似乎表现得像普通异步控制器(带异步和方法完成的那些)。有没有办法使用异步的方式/等待在控制器为我的情况?


解决方案

  

很显然,我可以开始一个新的线程手动处理文件,但我不知道我是否可以使用异步实现这个场景/等待着引进机制。NET 4.5


不,你不能,因为<一href=\"http://nitoprograms.blogspot.com/2012/08/async-doesnt-change-http-protocol.html\"><$c$c>async不改变HTTP协议

Svick和詹姆斯都已经公布正确答案的意见,这是我在下面复制方便:


  

IIS可以回收您的应用程序pretty很多在任何时候。


  
  

如果你有长时间运行的事情要做异步的请求,做他们在别处。 典型是一个持久性队列(MSMQ,天青,RabbitMQ的等),用别的东西(窗口服务,由任务调度运行exe文件,使用Quartz.net应用程序等),处理它们。


要总结,HTTP为您提供了一个请求和一个响应(异步 - 和其他任何 - 不会改变这一点)

ASP.NET是围绕HTTP请求设计(并使得假设,如如果没有优秀的请求,那么它的安全,停止本网站)。您的可以的启动新的线程,并保持你的上传在内存中(这是做的最简单的方法),但我们强烈不推荐使用。

有关你的情况,我建议你按照詹姆斯的建议是:


  • 当您已完成上传,保存上传至永久存储(例如,一个Azure的队列),并返回一个票给浏览器。

  • 有一些其他的方法(例如,一个蓝色的辅助角色)处理队列中,最终将其标记为完成。

  • 让浏览器民调以其票的服务器。服务器使用票来查找文件中永久存储和返回它是否是完整的。

有一些变型中,以本(例如,使用SignalR当处理完成通知浏览器),但一般结构是相同的。

这是复杂的,但它是应该做的正确方法。

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.

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;
}

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.

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?

解决方案

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

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

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

IIS can recycle your application pretty much at any time.

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.

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

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.

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

  • When your upload completes, save the upload to persistent storage (e.g., an Azure queue), and return a "ticket" to the browser.
  • Have some other process (e.g., an Azure worker role) process the queue, eventually marking it as complete.
  • Have the browser poll the server with its "ticket". The server uses the "ticket" to look up the file in persistent storage and return whether or not it's complete.

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 +异步/伺机+返回响应操作完成之前的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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