1

我有一个动作(控制器动作)在某些情况下可能需要几分钟才能运行。我想为我们的用户提供操作正在运行的视觉指示,例如消息、微调器或进度条。问题是,我很难弄清楚如何在前端“检测” Action 已经完成。

在对此进行了一番研究之后,我偶然发现了一篇题为“在 ASP.NET MVC 4 中使用异步方法”的文章。它解释了异步操作和 .NET 任务的使用。它看起来不错,我将花一些时间研究它,但我对这个概念太陌生了,无法真正理解它是否会给我我想要的东西。

所以,我对 SO 社区的问题是,如果您在异步操作和任务方面有很多经验,这些是否会帮助我在我的操作执行时向我的用户提供视觉反馈?或者,我是不是走错路了?

编辑:

感谢大家的回应。很抱歉我延迟返回这个。在发布了这个之后,我意识到我的情况有点不对劲。事实证明,我真正需要的是一个 FileResult,它生成一个 PDF,然后将其返回给浏览器,并在生成文件时向用户显示一个视觉指示器。

在我看来,这是一个完全不同的问题。所以,我会把它作为一个单独的问题发布。

4

3 回答 3

2

使用异步控制器会释放 IIS 请求线程,但它不会帮助您解决问题。如果您不担心同时进入许多长时间运行的用户请求(足以使 IIS 请求池饿死),您可能不需要在这方面做太多研究。

如果您有传统的 Post、Redirect、Get 流程,您可以轻松地在 post 上显示一个微调器,当浏览器获得响应并重定向到新页面时,该微调器将消失。

如果您使用的是异步 JavaScript,则可以在调用中显示微调器并将其隐藏在完成处理程序中。

我建议您不要尝试从 IIS 启动自己的后台任务或线程,因为它可以随时回收您的应用程序域。对于用户请求,它通常会停止,但它不会知道您启动的任何其他后台任务。您可以向 IIS 注册您的对象,因此它会在打算拆除您的应用程序域之前首先通知您,但您最多只能推迟 30 秒,然后 IIS 将继续运行。由于您的工作通常需要比这更长的时间才能完成,因此我建议这种更复杂的路线可能对您不太适用,并且会使您的代码更加复杂。

这真的取决于您的要求。让用户在继续使用您的应用程序之前等待工作完成是否可以,或者他们是否需要能够在等待工作完成时继续交互?

如果您可以让他们等待,请使用 Post、Redirect、Get 模式和您在提交时弹出的模式微调器。

如果用户必须能够继续工作,您将需要 PartialResponse 操作和带有处理程序的 AJAX 调用来显示和隐藏非模态微调器以指示工作正在进行中。

于 2014-01-31T23:06:01.267 回答
0

您可以简单地拥有一个页面,然后对您的操作启动 AJAX 请求。当您启动请求时,显示一个微调器。

然后,当 AJAX 请求成功或出错时,您将隐藏微调器。

使用这种方法,您不需要让 Action 方法是异步的,因为您不会占用 UI。

于 2014-01-31T22:50:56.483 回答
0

这是我采用较长运行进程以避免阻塞 UI 线程并向用户提供视觉反馈的方法的一个示例。

我将使用生成报告示例进行演示,这需要 .net 4.5。

围绕返回任务的报告生成处理创建一个方法。

作为一个例子,请看下面:

private Task RunReport() 
{
    return Task.Run(() => 
              // The below should contain your generate report code
              Thread.Sleep(5000)
     );
}

然后让你的Action回报成为一个任务,并await在调用报告之前放一个。

这将解锁 UI 线程,允许用户在生成报告时继续使用该站点。内容是完成处理后将返回到页面的内容。

[HttpPost]
public async Task<ActionResult> RequestReportGen()
{
    await RunReport();
    // Add your link to the report in the content below
    return Content("Report generated!";
}

包括以下 javascript 库:

<script src="@Url.Content("~/Scripts/jquery-1.8.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

然后使用 ajax 表单发布到您的方法,请注意LoadingElementId(等待时显示)和UpdatedTargetId(显示完成的消息)。

 @using (Ajax.BeginForm("RequestReportGen", "Home", new AjaxOptions { UpdateTargetId = "result", LoadingElementId="loading" }))
 {
        <div id="loading" style="display:none;">Generating Report...</div>
        <div id="result"></div>
        <input type="submit" />
}

使用上述方法,您的用户仍然可以使用该站点,因为您的 UI 线程不会被阻止,并且消息会在加载和完成时转发回用户。

于 2014-01-31T23:07:36.747 回答