在asp.net/angularjs中轮询长时间运行进程的进度

时间:2017-09-21 22:16:16

标签: asp.net angularjs asynchronous

我有一个旧的asp.net网站我一直在慢慢重构使用angularjs。我的一个页面调用了一个非常长的运行过程,我想让用户随时了解进度,并保持会话处于活动状态。

我认为我可以通过使用如下的一些angularj来实现这一点:

    $scope.setupLongRunningProcess= function() {
        $scope.progress = {};
        $scope.result = null;

        startLongRunningProcess();

        $timeout(function () {
            pollProgress();
        }, 5000);
    }

   function pollProgress() {
        if (!$scope.result) {
            $http({
                method: "POST",
                url: "MyPage.aspx/PollProgressJson",
                data: {}
            }).then(function successCallback(response) {
                $scope.progress.Count = response.data.d;

                $timeout(function() {
                        pollProgress();
                }, 5000);
            });
        }
    }

    function startLongRunningProcess() {
        $http({
            method: "POST",
            url: "MyPage.aspx/LongRunningProcessJson",
            data: {}
        }).then(function successCallback(response) {
            $scope.result = response.data.d;
        });
    }

它开始OK,调用调用MyPage.aspx / LongRunningProcessJson的startLongRunningProcess(),然后按预期调用pollProgress()。但是,它永远不会到达服务器上的MyPage.aspx / PollProgressJson。服务器上长时间运行的进程只是一个常见的WebMethod:

<WebMethod>
Public Shared Function LongRunningProcessJson(...) As Result(Of String)
    Dim service As LongRunningProcessService = GetService...
    Return service.LongRunningProcess(..., HttpContext.Current.Session)
End Function

在这里,我使用Http Session来计算进度,所有PollProgressJson正在进行查询。

我不想让我对LongRunningProcessJson的原始调用完成,直到它完成,所以我应该在那里进行异步调用来完成所有工作(并等到它完成后再返回)?

或者,我采取了错误的方法吗? (是的,我知道,我不喜欢将Session对象传递给我的业务层,它确实感觉非常icky)

我也尝试过制作LongRunningProcessJson WebMethod异步,但不会调用PollProgressJson:

<WebMethod>
Public Shared Async Function LongRunningProcessJson(...) As Threading.Tasks.Task(Of Result(Of String))
    Dim service As LongRunningProcessService = GetService...
    Return Await Task.Run(Function() service.LongRunningProcess(..., HttpContext.Current.Session))
End Function

2 个答案:

答案 0 :(得分:0)

您可以使用$ q service notify()函数来检查进度状态。详情请见https://docs.angularjs.org/api/ng/service/ $ q

答案 1 :(得分:0)

因此,事实证明,Asp.Net页面排队请求(通过持有会话锁定),可能正在写入同一个会话,这只能在页面级别关闭(除非当然,您的整个网络应用程序并不需要它,而不是WebMethod级别。所以解决方案是添加:

<%@ Page .... EnableSessionState="ReadOnly" ...." %>

到我的页面指令,并删除使用Session来编写进度(我还是不喜欢这样做)。相反,您可以使用数据库,全局变量(yuk)或文件来存储和查询您的临时进度。

注意:我相信MVC你可以通过添加属性在Controller级别做同样的事情:

[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]