0

このコードは、この例に基づいてい ますhttp://weblogs.asp.net/seanmcalinden/archive/2009/11/15/asynchronous-processing-in-asp-net-mvc-with-ajax-progress-bar.aspx MVC3、C#、jQuery、Ajax++

私のhtml

<div>
   <a href="#" id="startProcess">Start Long Running Process</a>
</div>
<br />
<div id="statusBorder">
    <div id="statusFill">
    </div>
</div>

html の JavaScript 部分部分

    var uniqueId = '<%= Guid.NewGuid().ToString() %>';

    $(document).ready(function (event) {
        $('#startProcess').click(function () {
            $.post("SendToDB/StartLongRunningProcess", { id: uniqueId,
                                 //other parameters to be inserted like textbox

                                                             }, function () {
                $('#statusBorder').show();
                getStatus();
            });
            event.preventDefault;
        });
    });

    function getStatus() {
        var url = 'SendToDB/GetCurrentProgress/' + uniqueId;
        $.get(url, function (data) {
            if (data != "100") {
                $('#status').html(data);
                $('#statusFill').width(data);
                window.setTimeout("getStatus()", 100);
            }
            else {
                $('#status').html("Done");
                $('#statusBorder').hide();
                alert("The Long process has finished");
            };
        });
    }

クラス全員でお手伝いします

public class ProgressBarManager
{

    private static object syncRoot = new object();

    /// <summary>
    /// Gets or sets the process status.
    /// </summary>
    /// <value>The process status.</value>
    private static IDictionary<string, int> ProcessStatus { get; set; }

    /// <summary>
    /// Initializes a new instance of the <see cref="MyLongRunningClass"/> class.
    /// </summary>
    public ProgressBarManager()
    {
        if (ProcessStatus == null)
        {
            ProcessStatus = new Dictionary<string, int>();
        }
    }

    /// <summary>
    /// Processes the long running action.
    /// This is how it was in sample code. Not used anymore.
    /// </summary>
    /// <param name="id">The id.</param>
    //public string ProcessLongRunningAction(string id)
    //{
    //    for (int i = 1; i <= 100; i++)
    //    {
    //        Thread.Sleep(100);
    //        lock (syncRoot)
    //        {
    //            ProcessStatus[id] = i;
    //        }
    //    }
    //    return id;
    //}

    public void SetStatus(string id, int value)
    {
        lock (syncRoot)
        {
            ProcessStatus[id] = value;
        }
    }

    /// <summary>
    /// Adds the specified id.
    /// </summary>
    /// <param name="id">The id.</param>
    public void Add(string id)
    {
        lock (syncRoot)
        {
            ProcessStatus.Add(id, 0);
        }
    }

    /// <summary>
    /// Removes the specified id.
    /// </summary>
    /// <param name="id">The id.</param>
    public void Remove(string id)
    {
        lock (syncRoot)
        {
            ProcessStatus.Remove(id);
        }
    }

    /// <summary>
    /// Gets the status.
    /// </summary>
    /// <param name="id">The id.</param>
    public int GetStatus(string id)
    {
        lock (syncRoot)
        {
            if (ProcessStatus.Keys.Count(x => x == id) == 1)
            {
                return ProcessStatus[id];
            }
            else
            {
                return 100;
            }
        }
    }
}

これはコントローラーで、おそらく私が何か間違ったことをしている場所です。

    delegate string ProcessTask(string id);
    ProgressBarManager longRunningClass = new ProgressBarManager();
    //Some global variables. I know it is not "good practice" but it works.
    private static int _GlobalSentProgress = 0;
    private static int _GlobalUsersSelected = 0;

    /// <summary>
    /// Starts the long running process.
    /// </summary>
    /// <param name="id">The id.</param>
    public void StartLongRunningProcess(string id,
                                        //other parameters
                                        )
    {
        longRunningClass.Add(id);

        int percentDone = 0;
        var batchId = Guid.NewGuid().ToString("N");
        var costd = cost.ToDecimal();
        int sent = 0;

        IEnumerable<BatchListModel> users;

        users = new UserService(_userRepository.Session).GetUsers(
                //several parameters)

        foreach (var c in users)
        {
            try
            {
                var usr = _userRepository.LoadByID(c.ID);

                var message = new DbLog
                {
                    //insert parameters
                };

                _DbLogRepository.Save(message);
                sent++;

                //MyLog.WriteLine("Sent = " + sent); This is  1 more each time it loops
                //MyLog.WriteLine("GlobalUsersSelected = " + _GlobalUsersSelected); This one is set in another function not shown.

                double _GlobalSentProgress = (double)sent / (double)_GlobalUsersSelected * 100;
                //MyLog.WriteLine("SentProgress = " + _GlobalSentProgress);

                if (percentDone < 100)
                {
                    //percentDone = doSomeWork();
                    percentDone = Convert.ToInt32(_GlobalSentProgress);
                    //MyLog.WriteLine("percentDone = " + percentDone); This one shows same as GlobalSentProgress except the decimals are removed
                    longRunningClass.SetStatus(id, percentDone);
                }

            }
            catch (Exception e)
            {
                MyLog.WriteLine("ERR:" + e);
            }
        }
        longRunningClass.Remove(id);


        //Under here is how it was done in the example tutorial. 
        //I think these should be implemented somehow.
        //This may be the root of my problem

        //ProcessTask processTask = new ProcessTask(longRunningClass.ProcessLongRunningAction);
        //processTask.BeginInvoke(id, new AsyncCallback(EndLongRunningProcess), processTask);


    }

    /// <summary>
    /// Ends the long running process.
    /// </summary>
    /// <param name="result">The result.</param>
    public void EndLongRunningProcess(IAsyncResult result)
    {
        ProcessTask processTask = (ProcessTask)result.AsyncState;
        string id = processTask.EndInvoke(result);
        longRunningClass.Remove(id);
    }

    /// <summary>
    /// Gets the current progress.
    /// </summary>
    /// <param name="id">The id.</param>
    public ContentResult GetCurrentProgress(string id)
    {
        this.ControllerContext.HttpContext.Response.AddHeader("cache-control", "no-cache");
        var currentProgress = longRunningClass.GetStatus(id).ToString();
        return Content(currentProgress);
    }

誰が何が間違っているのか知っていますか? どんな助けでも大歓迎です。私は何日も立ち往生しています。

「進行状況」を更新するはずのいくつかのブレークポイントは、挿入が 100% 完了するまで入力されません。現在、進行状況バーのある div は表示されません。

編集:挿入を行うループでは、次の計算があります。

double _GlobalSentProgress = (double)sent / (double)_GlobalUsersSelected * 100;

次に、_GlobalSentProgress を通常の int に変換します。

percentDone = Convert.ToInt32(_GlobalSentProgress);

そのため、小数はもうありません。

この「percentDone」変数 (挿入に何パーセント入ったかを完全に示しています) を、ループするたびに javascript の「data」変数に非同期で送信できれば、機能します。次に、「data」は常に「statusFill」を実行し、バーを正しく表示します。

    function getStatus() {
        var url = 'SendToDB/GetCurrentProgress/' + uniqueId;
        $.get(url, function (data) {
            if (data != "100") {
                $('#status').html(data);
                $('#statusFill').width(data);
                window.setTimeout("getStatus()", 100);
            }
            else {
                $('#status').html("Done");
                $('#statusBorder').hide();
                alert("The Long process has finished");
            };
        });

しかし、正直に言うと、非同期変数を扱うのはこれが初めてなので、このようなことを行う方法について非常に迷っています。

4

2 に答える 2

0

プログレスバーを表示するためにデザイナーの助けを借りたい、CSSで要素をdivするとします

<div id="divProgressBar" >/div>
 $(document).ready(function (event) {
    $('#startProcess').click(function () {
        $('#divProgressBar').show();//My code here
   }
}

function getStatus() {
    var url = 'SendToDB/GetCurrentProgress/' + uniqueId;
    $.get(url, function (data) {
        if (data != "100") {
            $('#status').html(data);
            $('#statusFill').width(data);
            window.setTimeout("getStatus()", 100);
        }
        else {
            $('#status').html("Done");
            $('#statusBorder').hide();
            $('#divProgressBar').hide();//My code here
            alert("The Long process has finished");
        };
    });
}

サードパーティのJSを使用してUIをブロックすることもできます。

http://www.malsup.com/jquery/block/

于 2013-02-25T18:07:16.113 に答える
0

このような問題が発生した場合、最初に行うことは、ブレークポイントまたはデバッガー (js で) を設定し、コードのどの部分が何かを行っているかを確認することです。

Jquery.postのドキュメントを見ると、ステータスバーが表示されないと言われています

リクエストが成功した場合に実行されるコールバック関数。

これは、クエリが成功しなかったため、表示されません。したがって、最初にコード内のどこで問題が発生しているかを確認します (C#)

于 2013-02-25T15:08:24.857 に答える