2012-10-14 77 views
4

我正在嘗試爲長時間運行的異步任務設置一個簡單的html進度欄。問題是我試圖啓動回發來運行一些服務器代碼,並同時執行客戶端單擊事件來啓動ajax輪詢,這會導致ajax調用中返回錯誤。這裏是我的jQuery和HTML代碼:在異步操作期間通過jQuery ajax更新ASP.net進度條

<%@ 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; 
    } 
} 

Apparnetly當點擊按鈕與Ajax調用干擾的回傳。如果我在javascript clickhandler中添加preventDefault,則回發從不會觸發(duh),但所有ajax調用都可以工作,所以至少所有的ajax代碼都可以正常工作。有沒有辦法讓按鈕都回發,所以我的服務器代碼可以運行,並做一個客戶端點擊事件,所以我可以啓動ajax調用?我認爲我在這裏搞砸了,我需要這樣做,沒有asp回發,因爲那時頁面被銷燬並重新加載,對吧?

我敢肯定,我對這一切都是錯誤的。我試着將所有這些都轉移到了一個服務上,我想避免所有的回發,並且只對服務進行ajax調用來完成異步工作,並且調查服務的完成百分比,但服務不實現頁面異步,所以沒有「RegisterAsyncTask ()「可以在.aspx頁面上調用。

我也試圖使用會話狀態來傳達異步任務和ajax調用之間完成百分比的值,我不知道它是否可以工作,但我想我會做實驗。如果失敗,我需要一些方法來傳達後臺任務和ajax調用之間的百分比。

我讀過很多關於如何在Web服務生成的代理中製作異步web服務和使用Beginxxx調用等的問題,但我也發現很多人試圖做類似於我的事情,通過jQuery進行簡單的Ajax調用,沒有運氣,也沒有真正的答案,因爲我可以找到。

因此,從.aspx頁面開始,如何使用頁面異步或服務啓動長時間運行的任務,並在任務運行時更新簡單的html5進度欄?似乎這將是簡單的,但沒有:\

回答

2

你只是缺少一個基本點。您的ajax通話無法通過回傳。

您無法通過按鈕點擊PROGRESS.startProgress(),導致您希望頁面在此之後立即回發。回發會導致您的ajax呼叫被終止。

如果您想要顯示進度條,則必須使用ajax而不是使用回發來上傳文件。有像uploadify這樣的插件可以提供幫助。

+0

我明白了。以下是事件的基本順序。我堅持使用asp.net上傳控件來獲取文件。在上傳按鈕處理程序中,我關閉了異步導入任務,然後設置了一個隱藏字段來指示我的javascript開始輪詢。異步任務將整個文件吸入到MemoryStream中(我不上傳大文件)然後開始處理。當它工作時,它獲取,更新並存儲在會話數據中完成的百分比。在我的JavaScript中,如果設置了隱藏字段,它會通過ajax開始輪詢我的WebMethod。aspx文件來獲取當前從會話中完成的百分比。 –

+0

您可以發佈解決方法的更新代碼嗎? @EricSassaman –

0

經歷了很多痛苦和痛苦之後,我完全重寫了我的解決方案,以使用SignalR,它極大地簡化了所需的所有代碼。有關在Web Forms網站中使用SignalR的長期運行任務的簡單HTML5進度條的簡單方法的更多詳細信息,see my blog post關於此主題的信息,其中包括可下載的極簡主義樣本和在線演示。我希望有人發現有幫助。