Simple BackgroundWorker未更新网页上的标签

本文关键字:标签 网页 更新 BackgroundWorker Simple | 更新日期: 2023-09-27 18:00:37

我使用了一段来自后

它使用一个按钮和一个标签,标签应该报告"完成10%"。。。"完成20%"。。。等等

当我调试时,代码被击中,但我的标签没有在浏览器上更新。

我试过用&没有更新面板,有和没有主页。

protected void btnStartThread_Click(object sender, EventArgs e)
    {
        BackgroundWorker bw = new BackgroundWorker();
        // this allows our worker to report progress during work
        bw.WorkerReportsProgress = true;
        // what to do in the background thread
        bw.DoWork += new DoWorkEventHandler(delegate(object o, DoWorkEventArgs args)
        {
            BackgroundWorker b = o as BackgroundWorker;
            // do some simple processing for 10 seconds
            for (int i = 1; i <= 10; i++)
            {
                // report the progress in percent
                b.ReportProgress(i * 10);
                Thread.Sleep(1000);
            }
        });

        // what to do when progress changed (update the progress bar for example)
        bw.ProgressChanged += new ProgressChangedEventHandler(delegate(object o, ProgressChangedEventArgs args)
        {
            label1.Text = string.Format("{0}% Completed", args.ProgressPercentage);
        });

        // what to do when worker completes its task (notify the user)
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        delegate(object o, RunWorkerCompletedEventArgs args)
        {
            label1.Text = "Finished!";
        });
        bw.RunWorkerAsync();

Simple BackgroundWorker未更新网页上的标签

您可能会进行长时间的轮询以获得更新的结果。就我个人而言,我不会在Web应用程序中使用后台工作者。此外,还可以考虑查看SignalR、服务器发送的事件、异步和等待或任务并行库。

BackgroundWorker不适合ASP。NET,并且不与ASP。NET非常好,因为ASP。NET在请求/响应模型上工作。要接收任何更新,客户端的浏览器需要从服务器请求信息。例如,要更新Label,您需要向服务器发送对其新值的请求。

一种选择是在客户端使用AJAX来更新页面。但是,您可以使用iframe,而不是使用正式的AJAX,这是异步执行长时间运行的流程的好方法,而不依赖于任何特定的AJAX框架。当点击按钮时,会动态生成一个不可见的iframe,用于在后台执行LongRunningProcess.aspx

<head runat="server">
<script type="text/javascript">
    function BeginProcess() {
        var iframe = document.createElement("iframe");
        iframe.src = "LongRunningProcess.aspx";
        iframe.style.display = "none";
        document.body.appendChild(iframe);
        document.getElementById('trigger').disabled = true;
    }
    function UpdateProgress(PercentComplete, Message) {
        document.getElementById('<%= Label1.ClientID %>').innerHTML = PercentComplete + '% ' + Message;
}
</script>
</head>
<body>
   <form id="form1" runat="server">
   <div>
    <input type="submit" value="Start Long Running Process" id="trigger" 
       onclick="BeginProcess(); return false;" style="width: 185px;"/>
    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
   </div>
   </form>
</body>

LongRunningProcess.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
{
   for (int i = 1; i <= 9; i++)
   {
       UpdateProgress(i * 10, " Completed.");
       System.Threading.Thread.Sleep(1000);
   }
   UpdateProgress(100, "Finished!");
}
protected void UpdateProgress(int PercentComplete, string Message)
{
    Response.Write(String.Format("<script type='"text/javascript'">parent.UpdateProgress({0}, '{1}');</script>", PercentComplete, Message));
    Response.Flush();
}

你可以在这里看到结果,也可以在Dave Ward的精彩文章中阅读更多:针对长时间请求的轻松增量状态更新。

这是罕见的,但。NET有时可以同步运行异步任务(从MSDN上的文档中还不清楚何时会发生这种情况),但如果在您的情况下发生这种情况,它将阻止WinForms应用程序中的消息循环。

为了测试这个理论,你可以试着提出一个应用程序。在ProgressChanged处理程序和DoWork处理程序中调用DoEvents(),看看这是否有帮助。这是一个丑陋的解决方案,但如果disptacher正在同步运行您的任务,它应该会强制UI更新。

您基本上有两个选项。

首先,您可以使用JavaScript从浏览器的计时器上进行轮询,以获得当前的完成百分比。setInterval是显而易见的方法,您可以使用jQuery或类似的方法对服务器进行AJAX调用。不过,这在一定程度上是低效的,因为您的服务器听起来知道什么时候正在进行或完成,所以服务器应该引发事件。

第二,这更符合你的需求,那就是使用SignalR。您已经将事情设置为在引发计时事件时从服务器"推送",但在HTTP中没有简单的方法可以做到这一点(HTML5 WebSockets也是一种替代方案)。使用SignalR这样的服务器推送技术,可以创建向客户端发送事件的"集线器"。它们可以是特定于用户的目标事件,也可以是所有客户端类型的事件,由您决定。

点击此处查看简介/演示。他们让一个相当棘手的问题变得很容易:http://www.asp.net/signalr

正如其他人所提到的,你可能不想使用BackgroundWorker。尝试QueueBackgroundWorkItem。http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx