5

我有一个简单但耗时的操作:当用户单击一个按钮时,它会执行数据库密集型操作,将导入表中的记录处理到其他多个表中,一次导入一条记录。我有一个带有触发操作的按钮的视图,并在操作结束时显示报告。

我正在寻找通知用户正在处理操作的方法。这是我喜欢的解决方案。

我一直在网上阅读有关 MVC 中的异步操作的信息。我发现许多链接说如果您的进程受 CPU 限制,请坚持使用同步操作。数据库相关进程是否被视为 CPU 受限?

此外,如果我得到了异步操作路线,我应该使用此处描述的 AsyncController还是仅使用我提到的示例中的 Task 以及此处的示例。还是它们都一样?

4

3 回答 3

3

假设 C# 5.0,我会做这样的事情如下:

// A method to get your intensive dataset
public async Task<IntensiveDataSet> GetIntensiveDataSet() {
   //in here you'll want to use any of the newer await Async calls you find 
   // available for your operations. This prevents thread blocking.

    var intensiveDataSet = new IntensiveData();
    using (var sqlCommand = new SqlCommand(SqlStatement, sqlConnection))
        {
            using (var sqlDataReader = await sqlCommand.ExecuteReaderAsync())
            {
                while (await sqlDataReader.ReadAsync())
                {
                    //build out your intensive data set.
                }
            }
        }
    return intensiveDataSet;
}


// Then in your controller, some method that uses that:
public async Task<JsonResult> Intense() {
    return Json(await GetIntensiveDataSet());
}

在您的 JS 中,您可以这样称呼它(使用 JQuery):

$.get('/ControllerName/Intense').success(function(data) {
   console.log(data);
});

老实说,我只是在它运行时展示某种微调器。

如果您确实需要向用户提供某种反馈,则必须在整个异步调用期间对用户的 Session 进行更新......并且为了做到这一点,您需要传递对该 Session 的引用。然后,您只需添加另一个简单的 JsonResult 操作,该操作检查 Session 变量中的消息并使用 JQuery 定期轮询它。不过好像有点矫枉过正。在大多数情况下,简单的“这可能需要一段时间”对人们来说就足够了。

于 2013-02-20T02:35:25.997 回答
3

您需要知道的第一件事是它async不会改变 HTTP 协议。正如我在博客中所描述的,HTTP 协议为每个请求提供一个响应。因此,您不能在说它“正在进行中”后再次返回说它“已完成”。

简单的解决方案是仅在完成时返回,并使用 AJAX 在客户端抛出一些“正在进行中......”通知,在请求完成时更新页面。如果您想变得更复杂,您可以使用 SignalR 之类的东西让服务器在请求完成时通知客户端。

特别是,asyncMVC 操作不会返回“早期”;ASP.NET 将等待所有异步操作完成,然后发送响应。async服务器端的代码都是关于可伸缩性的,而不是响应能力。

也就是说,我通常建议在服务器端使用异步代码。一个例外是如果您只有一个数据库后端(在这篇博文中进行了很好的讨论)。如果您的后端是数据库集群或分布式/NoSQL/SQL Azure DB,那么您应该考虑使其异步。

如果你决定让你的服务器异步,只需 return Tasks; AsyncController这些天只是为了向后兼容。

于 2013-02-20T03:43:24.513 回答
0

您应该考虑使用 AJAX 实现异步的选项。您可以直接在您的视图中处理客户端“...处理”消息,而且麻烦最少,

$.ajax({
    url: @Url.Action("ActionName"),
    data: data
}).done(function(data) {
    alert('Operation Complete!');
});

alert('Operation Started');

// Display processing animation

在服务器端处理异步调用可能是昂贵、复杂和不必要的。

于 2013-02-20T02:13:44.050 回答