0

我遇到了以下问题,我想执行一段可能需要一段时间的代码。

如果用户必须等待它完成,那将是一个糟糕的用户体验。所以我想使用一个线程。

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

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

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

这是为什么?我如何让它发挥作用?

提前致谢!

4

1 回答 1

1

您在上面完成它的方式将不起作用,因为正如您所观察到的,您等待任务然后返回,所以从用户的角度来看,它实际上是一个同步操作,他们被困在等待服务器响应工作的实际结果。

不过有几种方法可以做到这一点,这取决于任务的性质。如果这是生成用户可能希望稍后返回并下载的数据的东西,例如可能需要一段时间才能生成的报告:

  1. 使用异步控制器,启动任务并通过一些唯一标识符在服务器端保存记录,然后立即返回该标识符。

    • 然后触发客户端脚本通过Ajax调用每 N 秒轮询一次,以查看服务器端的工作是否完成
    • 但是,如果应用程序池在IIS此线程运行期间被回收,则工作将丢失,并且您还没有真正的方法来控制它
  2. 更好的是在一个单独的进程中启动长时间运行的任务,然后客户端可以每隔几秒轮询一次(或SignalR从服务器端使用推送)来判断工作何时完成。

    • 实现这一点的典型方法是将要完成的工作的记录推送到 a 中Queue,然后将某种标识符返回给客户端。
    • 您的单独进程可以一直运行并监视队列以执行新工作,然后它可以使用工作结果更新数据库或缓存。
    • 同时,客户端正在轮询(或SignalR正在推送,您的信号器集线器每隔几秒检查一次并将作业状态推送回客户端)以查看该特定“作业”是否已完成。
    • 这样,您就不会受到 Web 服务器进程停机和丢弃所有线程的摆布,而且您可以更好地控制需要推迟作业、将负载分散到多个服务器等的情况。

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

于 2013-10-31T09:18:14.727 回答