0

基本的に、ループされている関数の進行状況を追跡します。この関数は Ajax によって呼び出されます。

たとえば、更新パネルがあります。

<form runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager> 

<asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="True" UpdateMode="Always">

<ContentTemplate> 

<div>
<asp:Label ID="testing" runat="server"></asp:Label>
</div>          

</ContentTemplate> 
<Triggers>

<asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click"/>
</Triggers>
</asp:UpdatePanel>

<div style="display:none;">
<asp:Button ID="myButton" Text="SomeFunction" OnClick="myFunc" runat="server">
/asp:Button>
</div>

...
</form>

コードビハインドでの私の機能は次のとおりです。

Protected Sub myFunc

  Dim i As Integer

    For = 0 to 1000

      'Some other function here consumes time

      testing.text = i.ToString

    Next

End Sub

Response.write が ajax と混同しないことを理解したので、ラベル オブジェクトを使用してテキストを更新し、関数のループの進行状況を追跡したいと考えています。

ただし、テキストは ajax 呼び出しが完全に終了するまで更新されないようで、ループの最後の番号にのみ変更されます。

私の質問は、ループ関数がまだサーバー側で実行されている間に、テキスト オブジェクトをリアルタイムで変更し続ける方法はありますか?

ありがとう!

4

2 に答える 2

0

他の訪問者のために、私は別のページから私の答えをコピーします:

.net updatepanelsを使用してこれを行うことはできません。少なくとも、簡単だとは思いません。あなたは2つの別々のAJAX呼び出しでそれを行うことができますが。

この例では、AJAXにJQueryを使用しており、コードビハインドはvb.netにあります。

基本的に、最初の呼び出しを行って長いプロセスを開始し、次に2番目のメソッドを使用して2番目の呼び出しを繰り返し、長いプロセスのステータスを取得する必要があります。

AJAX

これは、長いプロセスへの主な呼びかけです。必要に応じて、データをメソッドに渡す必要があります。processNameがあることに注意してください。このプロセスのステータスのみを取得できるように、これはランダムな種類の文字列である必要があります。他のユーザーは別のランダムなprocessNameを持つため、混乱したステータスになることはありません。

    var processName = function GenerateProcessName() {

        var str = "";
        var alhpabet = "abcdefghijklmnopqrstuvwxyz";
        for (i = 1; i < 20; i++) {
            str += alhpabet.charAt(Math.floor(Math.random() * alhpabet.length + 1));
        }
        return str;
    }


    function StartMainProcess(){
    $j.ajax({
            type: "POST",
            url: "/MyWebservice.asmx/MyMainWorker",
            data: "{'processName' : '" + processName + "','someOtherData':'fooBar'}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {
                if (msg.d) {                        
                    // do a final timerPoll - process checker will clear everything else
                    TimerPoll();
                }
            }
        });
        TimerPoll();
     }

2番目のAJAX呼び出しは、進行状況を取得するための別のメソッドへの呼び出しになります。これは、タイマー方式によってXXX回ごとに呼び出されます。

これはTimerPoll関数です。この場合、3秒ごとに起動します

function TimerPoll() {
        timer = setTimeout("GetProgress()", 3000)
    }

そして最後に、GetProgress()関数を使用して、進行状況を取得します。このユーザーの呼び出しのみのプロセスを取得するには、上記で使用したものと同じprocessNameを渡す必要があります

function GetProgress() {
        // make the ajax call
        $j.ajax({
            type: "POST",
            url: "/MyWebService.asmx/MyMainWorkerProgress",
            data: "{'processName' : '" + processName + "'}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {

                // Evaulate result..
                var process = msg.d

                if (process.processComplete) {
                    // destroy the timer to stop polling for progress
                    clearTimeout(timer);

            // Do your final message to the user here.                      

                } else {

                   // show the messages you have to the user.
                   // these will be in msg.d.messages

                    // poll timer for another trip
                    TimerPoll();
                }
        });

    }

これで、バックエンドに、AJAXが通信するいくつかのWebメソッドがあります。また、すべての進行状況情報と、ユーザーに返したいものを保持するための共有/静的オブジェクトも必要になります。

私の場合、MyMainWorkerProcessを呼び出すたびに、プロパティが入力されて返されるクラスを作成しました。これは少しこのように見えます。

    Public Class ProcessData
        Public Property processComplete As Boolean
        Public Property messages As List(Of String) = New List(Of String)
    End Class

このクラスを使用する共有プロパティもあります。これは次のようになります...(この共有プロパティは、複数のユーザーによる複数のプロセスの進行状況を保持できます。したがって、辞書です。辞書のキーはプロセス名になります。すべての進行状況データはクラスProcessDataに含まれる

Private Shared processProgress As Dictionary(Of String, ProcessData) = New Dictionary(Of String, ProcessData)

私のメインワーカー関数は少しこのように見えます。最初に、同じプロセスが別のprocessProgressにないことを確認します。

<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function MyMainWorker(ByVal processName as string, ByVal SomeOtherData as string) as Boolean

        '' Create progress object - GUI outputs process to user
        '' If the same process name already exists - destroy it
        If (FileMaker.processProgress.ContainsKey(processName)) Then
            FileMaker.processProgress.Remove(processName)
        End If

        '' now create a new process
        dim processD as ProcessData = new ProcessData() with {.processComplete = false}


        '' Start doing your long process.

        '' While it's running and after whatever steps you choose you can add messages into the processData which will be output to the user when they call for the updates
         processD.messages.Add("I just started the process")

         processD.messages.Add("I just did step 1 of 20")

         processD.messages.Add("I just did step 2 of 20 etc etc")

         '' Once done, return true so that the AJAX call to this method knows we're done..
        return true

End Function

あとは、progressメソッドを呼び出すだけです。これから行うのは、前に設定したのと同じprocessNameを持つディクショナリprocessDataを返すことだけです。

<WebMethod()> _
    <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
    Public Function MyMainWorkerProgress(ByVal processName As String) As ProcessData

        Dim serializer As New JavaScriptSerializer()

        If (FileMaker.processProgress.ContainsKey(processName)) Then
            Return processProgress.Item(processName)
        Else
            Return New ProcessData()
        End If

    End Function

そして出来上がり..

要約すると..

  1. 2つのWebメソッドを作成します。1つは長いプロセスを実行し、もう1つは進行状況を返します。
  2. これらのWebメソッドへの2つの別々の呼び出しを作成します。1つ目はメインワーカー、2つ目はxx秒間繰り返され、進行状況を示すものです。
  3. 適切と思われる方法でユーザーにメッセージを出力します...

免責事項...私はこれまでここでこれほど長い間答えを提供していませんでした..それは人々が見慣れている形式に従わないかもしれません。すべてが少し混乱しているように思われる場合は申し訳ありません:)実行中のプロジェクトからほとんどのコードをコピーしたので、動作するはずです。ただし、タイプミスがいくつかある場合は撃たないでください:)

于 2012-11-09T15:02:26.270 に答える
0

はい、可能です。しかし、これは単純な解決策ではありません。Dino Esposito には、このトピックに関する優れた記事が多数あります。

ASP.NET AJAX でサーバー タスクをキャンセルする - http://msdn.microsoft.com/en-us/magazine/cc163380.aspx SignalR でプログレス バーを作成する - http://msdn.microsoft.com/en-us/magazine /hh852586.aspx

私に関しては、私のプロジェクトの 1 つで、最初の記事で説明したアプローチを使用しました。

于 2012-11-08T20:52:15.673 に答える