4

我正在尝试为长时间运行的异步任务设置一个简单的 html 进度条。问题是我试图触发回发以运行一些服务器代码并同时执行客户端单击事件以启动 ajax 轮询,这导致 ajax 调用中返回错误。这是我的 jQuery 和 html 代码:

<%@ Page Language="C#" AsyncTimeout="230" CodeFile="test.aspx.cs" Inherits="test" %>

<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script>
        "use strict";
        var PROGRESS;
        $(document).ready(function () {
            $.ajaxSetup({
                type: "POST",
                contentType: "application/json",
                data: '{}',
                timeout: 10000,
                converters: {
                    "text json": function (data) {
                        var msg;
                        msg = $.parseJSON(data);
                        return msg.hasOwnProperty('d') ? msg.d : msg;
                    }
                }
            });
            PROGRESS = {
                done: false,
                startProgress: function () {
                    var _progress = this;
                    $.ajax({
                        url: 'test.aspx/getProgress',
                        timeout: 20000,
                        data: '{}',
                        dataType: "json",
                        success: function (data) {
                            var currProgress = data * 100;
                            $("#prog").value = currProgress;
                            if (currProgress > 99)
                                _progress.done = true;
                            else
                                setTimeout("PROGRESS.startProgress()", 5000);
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            var s = textStatus == null ? "" : textStatus;
                            s += errorThrown == null ? "" : ", " + errorThrown;
                            alert(s);
                        }
                    });
                }
            };
            $("#body_DoUploadButton").on("click", function (event) {
                //event.preventDefault();
                PROGRESS.startProgress();
            });
        });
    </script>
</head>
<body>
    <asp:Button ID="DoUploadButton" Text="Import file" OnClick="UploadButton_Click" runat="server"></asp:Button>
    <progress id="prog" value="0" max="100"></progress>
</body>

这是我的代码隐藏:

public partial class test : System.Web.UI.Page
{
    delegate void AsyncTaskDelegate();
    AsyncTaskDelegate _dlgt;

    IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData)
    {
        _dlgt = new AsyncTaskDelegate(DoImport);
        IAsyncResult result = _dlgt.BeginInvoke(cb, extraData);
        return result;
    }

    void OnEnd(IAsyncResult ar)
    {
        _dlgt.EndInvoke(ar);
    }

    void OnTimeout(IAsyncResult ar)
    {
        //do something
    }

    [WebMethod(EnableSession = true)]
    public static double getProgress()
    {
        if (HttpContext.Current.Session["pctDone"] == null)
            return 0.0;
        return (double)HttpContext.Current.Session["pctDone"];
    }

    protected void DoImport()
    {
        int i = 10;
        while (i-- > 0)
        {
            System.Threading.Thread.Sleep(5000); //fake some work
            Session["pctDone"] = i / 10.0;
        }
        Session["pctDone"] = 1.0;
    }

    protected void UploadButton_Click(object sender, EventArgs e)
    {
        Session["pctDone"] = 0.0;
        PageAsyncTask task = new PageAsyncTask(new BeginEventHandler(OnBegin), new EndEventHandler(OnEnd),
            new EndEventHandler(OnTimeout), null);
        RegisterAsyncTask(task);
        ExecuteRegisteredAsyncTasks();
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        Server.ScriptTimeout = 240;
    }
}

显然,单击按钮时的回发会干扰 ajax 调用。如果我在 javascript clickhandler 中添加了 preventDefault,则回发永远不会触发(duh),但所有 ajax 调用都可以正常工作,因此至少所有 ajax 代码都可以正常工作。有没有办法让一个按钮既回发,所以我的服务器代码可以运行,并执行客户端点击事件,以便我可以启动 ajax 调用?我想我在这里搞砸了,我需要在没有asp回发的情况下完成这一切,从那时起页面被破坏并重新加载,对吧?

我确定我做错了。我尝试将所有这些转移到服务中,我认为我会避免所有回发,只需对服务进行 ajax 调用以完成异步工作并轮询服务以获取完成百分比,但服务没有实现页面异步,因此没有“RegisterAsyncTask ()" 像在 .aspx 页面上一样调用。

我还尝试使用会话状态来传达异步任务和 ajax 调用之间完成的百分比值,我不知道它是否会起作用,但我想我会尝试一下。如果它失败了,我需要某种方式来传达后台任务和 ajax 调用之间的百分比。

我已经阅读了很多关于如何在 web 服务生成的代理中进行异步 web 服务和使用 Beginxxx 调用等的文章,但我也发现很多人试图做与我类似的事情,进行简单的 ajax 调用通过 jQuery,并且没有运气,也没有我能找到的真正答案。

因此,如何从 .aspx 页面开始使用页面异步或服务启动长时间运行的任务,并在任务运行时更新简单的 html5 进度条?似乎这很简单,但没有:\

4

2 回答 2

2

你只漏掉了一个基本点。您的 ajax 调用将无法在回发后继续存在。

您不能PROGRESS.startProgress()在按钮单击时调用,因为您希望页面在此之后立即回发。回发会导致您的 ajax 调用被终止。

如果要显示进度条,您也必须使用 ajax 上传文件,而不是使用回发。有像uploadify这样的插件可以提供帮助。

于 2012-10-15T05:20:28.697 回答
0

在经历了许多痛苦和磨难之后,我完全重写了使用 SignalR 的解决方案,这极大地简化了所需的所有代码。有关在 Web 表单网站中使用 SignalR 为长时间运行的任务执行简单 HTML5 进度条的简单方法的更多详细信息,请参阅我关于该主题的博客文章,其中包括可下载的极简主义示例和在线演示。我希望有人觉得这很有帮助。

于 2014-02-11T06:59:23.027 回答