You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ajax异步请求中实现长进程状态轮询与进度条更新

Hey there! Your core idea of using client-side polling to track a long-running server process is solid, but there are a few critical tweaks needed to make this work reliably. Let's walk through the complete, working implementation:

1. Updated Controller Code

First, the status field needs to be static (since each HTTP request creates a new instance of the controller) and we should add thread safety to avoid race conditions between the long process and polling requests.

using System.Threading;
using System.Web.Mvc;

public class HomeController : Controller
{
    // Static field to hold process status (shared across all requests)
    private static int _status;
    // Lock object for thread-safe access to the status value
    private static readonly object _statusLock = new object();

    // Get current status (thread-safe)
    public JsonResult GetStatus()
    {
        lock (_statusLock)
        {
            return Json(_status, JsonRequestBehavior.AllowGet);
        }
    }

    // Set status (thread-safe helper method)
    private void SetStatus(int value)
    {
        lock (_statusLock)
        {
            _status = value;
        }
    }

    // Simulated long-running process (20 seconds total)
    public JsonResult LongProcess()
    {
        // Reset status at the start of the process
        SetStatus(0);
        
        // Loop from 1 to 10 to reach 100% progress
        for (int i = 1; i <= 10; i++)
        {
            Thread.Sleep(2000); // Simulate work with 2-second delays
            SetStatus(i);
        }

        return Json("Done", JsonRequestBehavior.AllowGet);
    }
}
2. Updated View Code

We'll add better user feedback, error handling, and ensure the progress bar behaves as expected when the process finishes:

<button class="btn btn-primary" id="progressBtn">Start Long Process</button>
<div class="progress mt-3" style="width: 500px;">
    <div class="progress-bar progress-bar-striped progress-bar-animated" 
         id="probar" 
         role="progressbar" 
         aria-valuenow="0" 
         aria-valuemin="0" 
         aria-valuemax="100" 
         style="width: 0%;">
        0%
    </div>
</div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$('#progressBtn').on('click', function () {
    const $btn = $(this);
    // Disable button to prevent duplicate clicks
    $btn.prop('disabled', true).text('Processing...');
    
    // Start polling for status updates every 250ms
    const intervalID = setInterval(updateStatus, 250);

    // Trigger the long-running server process
    $.ajax({
        type: "POST",
        url: '/Home/LongProcess',
        contentType: "application/json",
        dataType: "json",
        data: "{}",
        success: function () {
            clearInterval(intervalID);
            // Force progress to 100% when process completes
            updateProgress(100);
            $btn.prop('disabled', false).text('Process Completed');
        },
        error: function () {
            clearInterval(intervalID);
            $btn.prop('disabled', false).text('Process Failed');
            alert('An error occurred during the long process.');
        }
    });
});

function updateStatus() {
    $.ajax({
        type: "GET",
        url: '/Home/GetStatus',
        contentType: "application/json",
        dataType: "json",
        success: function(data) {
            // Convert 0-10 status value to 0-100% progress
            const percent = data * 10;
            updateProgress(percent);
        },
        error: function () {
            console.error('Failed to fetch process status');
        }
    });
}

// Helper to update progress bar UI
function updateProgress(percent) {
    const $bar = $('#probar');
    $bar.css('width', percent + '%')
        .attr('aria-valuenow', percent)
        .text(percent + '%');
}
</script>
3. Key Improvements & Notes
  • Thread Safety: The lock statement ensures that reading/writing the status doesn't cause race conditions when multiple requests (polling + long process) access the static field.
  • Static Status: Without making _status static, each controller instance would have its own status value, so polling requests would never see updates from the long process.
  • User Experience: Added button state changes, animated progress bar styling, and percentage text to keep users informed.
  • Error Handling: Properly cleans up the polling interval if the process fails, and gives clear feedback to the user.
  • Status Reset: The long process resets the status to 0 at startup, so repeated button clicks work correctly.

内容的提问来源于stack exchange,提问作者Murfcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:01:16