1

我有一个 MVC4 应用程序,它有一个或两个长时间运行的请求。为此,首先,迭代我将把这些作为同步任务。但是,我希望将这些任务的跟踪输出显示在我的 Web 应用程序的可选“进度”窗口上。

我看到了两个候选解决方案,涉及数据库跟踪侦听器或对会话中存储的“跟踪集合”对象具有权限的跟踪侦听器。然后“进度”窗口可以使用setIntervalAjax 调用定期轮询这些跟踪存储。

这听起来太简单了,这就是为什么我要问我应该怎么做。有没有更好的方法、既定的模式和技术,还是没有什么价值的练习?

4

1 回答 1

1

您可以使用SignalR将跟踪消息从服务器端直接发送到浏览器中的“进度窗口”。

Dino Esposito 在 msdn 上写了一篇文章,用进度条做了类似的事情。

这样您就不需要从进度窗口轮询服务器,也不需要使用 Session 来存储轮询请求之间的消息。


已编辑:添加示例

自从那篇文章写完之后,SignalR 发生了一些变化。除了在 global.asax 中注册路由并在视图中包含脚本之外,您还需要以下一段 javascript 来初始化客户端 signalR 代理并添加一个函数来显示进度信息:

<script type="text/javascript">
    $(document).ready(function () {    

        // Create a proxy for the server endpoint            
        var progressHub = $.connection.progressHub;
        $.connection.hub.start();

        // Add a client-side callback to process any data
        // received from the server
        progressHub.client.addProgress = function (message) {
            $('#progress').append('<li>' + message + '</li>');
        };

    });
</script>

假设您在该页面上有一个按钮,可以触发服务器中的长时间运行的进程。为简单起见,我将使用以下 jquery 调用来调用RunProcesshome 控制器中命名的方法。它将传递 SignalR 客户端的 id,以便服务器知道谁需要接收进度数据:

$("#runProcess").click(function () {                
    var id = $.connection.hub.id;
    $.get("/Home/RunProcess/" + id);
});

在服务器端,HomeController 的以下方法将模拟长时间运行的过程。为了使用 SignalR 通知客户端,您需要使用GlobalHost.ConnectionManager.GetHubContext<T>(). 然后它将需要调用addProgress(message)已在客户端代理上定义的方法,但仅针对具有接收到的 Id 的客户端:

public void RunProcess(string id)
{
    var progressHub = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();

    progressHub.Clients.Client(id).addProgress("25% completed");
    Thread.Sleep(2000);

    progressHub.Clients.Client(id).addProgress("50% completed");
    Thread.Sleep(3000);

    progressHub.Clients.Client(id).addProgress("75% completed");
    Thread.Sleep(2000);

    progressHub.Clients.Client(id).addProgress("Process Finished");
}
于 2013-05-26T20:20:36.907 回答