2013-10-31 34 views
0

我遇到了以下问题,我想执行一段可能需要一段时间的代码。在线程仍在运行时返回异步(MVC .Net)

如果用户不得不等待它完成,那将是一个糟糕的用户体验。所以我虽然使用线程。

[HttpPost] 
    public ActionResult methode(Model model){ 
    Task.Factory.StartNew(() => 
     { 
      // Do a block of code that takes a while 
     }); 
    return Json(new 
    { 
     succes = GetValue() 
    });   
} 

在调试时,您可以清楚地看到线程正在执行并且已到达返回码。

问题我在这里得到的结果是线程完成时的实际返回。 (所以我在这里没有获得任何速度)。

这是为什么?我如何使它工作?

在此先感谢!

回答

1

你上面这样做的方式将不起作用,因为正如你所观察到的,你已经等待任务,然后返回,如此有效地从用户的角度来看,它是一个同步操作,并且他们坚持等待服务器以实际工作结果作出回应。

虽然有几种方法可以做到这一点,但这取决于任务的性质。如果是这样的东西,产生的数据,用户可能要回来以后和下载如一个报告,可能需要一段时间来产生:

  1. 使用异步控制器,打完折的任务,并保持在服务器端通过一些唯一的标识符进行记录,然后立即用该标识符返回。

    • 一个客户端脚本,然后触发通过Ajax调用poll每隔N秒,看是否工作就完成了在服务器端
    • 但是,如果应用程序池被运行过程中IIS回收这个线程的,工作丢失,你还没有真正得到的方式来控制这种
  2. 更好的是在一个单独的进程揭开序幕长期运行的任务,然后客户端可以每隔几秒钟轮询(或当工作完成时,从服务器端使用SignalR推送)。

    • 一个典型的方式实现这一目标是推动工作的记录做成Queue然后返回某种标识的客户端。
    • 您的单独进程可以一直运行,并监视队列中的新工作,然后可以使用工作结果更新数据库或缓存。
    • 与此同时,客户端正在轮询(或SignalR正在推动您的信号中心每隔几秒检查一次并将作业状态推回到客户端)以查看是否完成了该特定“作业”。
    • 这样你就不会受到Web服务器进程的束缚而毁掉你的所有线程,再加上你可以更好地控制你需要推迟工作,将负载分散到多个服务器等情况。

如果在另一方面,这是数据,只是需要一段时间来计算,但只会提供给屏幕上的用户,并且不允许用户离开当前页面,同时等待结果,然后仅使用来自客户端的正确异步Ajax调用!

+0

感谢您的快速响应。任务内的任务不需要返回给客户端。它生成的数据将被保存在数据库中。所以最好和最简单的方法是异步控制器? – Jan

+1

@Jan - 在这种情况下,我认为没有必要有一个异步控制器。使用方法#2排队工作,然后立即返回给客户端。在完全独立的过程中执行工作。 –

+0

我不知道我该如何做到这一点,你可以提供一个代码片段或例子吗?提前致谢! – Jan