可以/我应该在这里使用异步控制器吗? (ASP.NET MVC 3)

时间:2011-01-19 07:17:57

标签: c# asp.net-mvc asynchronous asp.net-mvc-3

我有[HttpPost]动作方法:

[HttpPost]
public ActionResult AddReview(Review review)
{
   repository.Add(review);
   repository.Save();
   repository.UpdateSystemScoring(review.Id); // call SPROC with new Review ID.
   return View("Success", review);
}

因此,基本上用户单击一个按钮,我将其添加到我的数据库(通过Entity Framework 4.0),保存更改,然后我使用标识字段调用存储过程,这是第二行代码。< / p>

在保存审核之后需要完成(因为身份字段仅在调用Save时创建,EF保留更改),并且它是系统范围的计算。

从用户的角度来看,他/她不会/不应该关心此计算是否正在发生。

此过程可能需要0-20秒。它没有返回任何东西。

这是异步控制器的候选者吗?

有没有办法可以添加Review,让另一个异步控制器处理长时间运行的SPROC调用,这样用户可以立即进入Success页面?

我必须承认(部分感到羞耻):这是对现有系统的重写,在原始系统(ASP.NET Web Forms)中,我启动了另一个线程以便实现上述任务 - 这就是为什么我想知道是否可以将相同的主体应用于ASP.NET MVC 3。

我总是尝试并避免在ASP.NET中使用多线程,但用户体验是第一优先级,我不希望页面超时。

所以 - 这可能吗?也很高兴听到任何其他想法。另外 - 我不能在这里使用触发器,不是真的想详细说明为什么 - 但我不能。

4 个答案:

答案 0 :(得分:4)

我会触发一个新线程(不是来自线程池)来执行此任务并立即返回,尤其是如果您不关心结果。异步控制器在大部分时间用于等待其他系统完成任务的情况下非常有用,并且一旦此系统完成任务,您的应用程序就会发出信号以处理结果。在执行任务期间,不会从应用程序中消耗任何线程。因此,在您的场景中,SQL Server可以使用ADO.NET中的BeginRead方法的异步版本执行此任务。如果您需要返回结果,可以使用此选项。如果你没有开始新的线程就像以前一样工作。

答案 1 :(得分:1)

由于评分系统运行时间太长,我建议在SQL Server或Windows中使用计划任务每​​x分钟更新一次分数。由于用户不知道请求,因此立即运行并不重要。

您可以将ID添加到队列中,并每隔30分钟处理一次队列。

否则,如果有一个原因需要立即运行,你可以做一个asyc调用,或者看看你是否可以减少存储过程中的一些脂肪。

答案 2 :(得分:1)

我认为异步控制器更适用于请求可能需要很长时间才能返回响应的事情,但主线程将花费大部分时间等待另一个线程/进程。这对于ajax调用而不是主页面加载非常有用,只要在返回响应之前显示进度指示器是可以接受的。

我为这种类型的任务使用单独的排队系统,它更健壮,更易于使用,但确实需要更多的工作来设置。如果你真的需要在ASP.net进程中这样做,单独的请求可能是最好的选择,虽然有一些潜在的任务不能运行 - 例如我不确定如果连接丢失或者当异步任务正在运行时,应用程序池会循环使用。

答案 3 :(得分:1)

我有一个非常类似的系统。我们不是同步处理事务,而是使用队列进行异步操作。

Action -> causes javascript request to web server
   |
Web server puts notification on queue
   |
Worker picks up message from queue and does point calculation
   |
At some point in future user sees points adjusted

这使我们能够处理大量的用户负载,而不必担心这会对我们的计算引擎产生负面影响。这也意味着我们可以在我们有大负载时添加更多的工人来处理更大的负载,并且当我们没有大负载时可以移除工人。