【问题标题】:Simple BackgroundWorker is not updating label on web pageSimple BackgroundWorker 没有更新网页上的标签
【发布时间】:2014-04-29 12:31:34
【问题描述】:

我使用了这个有用的一段简单代码 post

它使用一个按钮和一个标签,标签应该报告“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();

【问题讨论】:

  • 如果 HTML 已经通过网络发送到客户端,您希望如何更新它?您需要在客户端上使用 AJAX 来更新页面。
  • 这就是为什么我认为页面上的脚本管理器和更新面板可以解决问题:/
  • 应该的。我不记得完全了,你确定你不需要调用像 updatePanel.Update(); 这样的东西吗?还是类似的?
  • 您需要使用 SignalR 之类的工具将该信号发送到客户端。
  • 在客户端服务器Web应用程序中,服务器不发起与客户端的通信,它只响应客户端的请求。您可以通过使用 ajax 请求或带有信号器 asp.net/signalr/overview/guide-to-the-api/… 的服务器推送模式来实现您想要的客户端拉取模式

标签: c# asp.net multithreading backgroundworker


【解决方案1】:

您可能会进行长时间轮询以获取更新的结果。就我个人而言,我不会在 Web 应用程序中使用后台工作者。此外,请考虑查看 SignalR、Server Sent Events 和 Async and Await 或 Task Parallel Library。

【讨论】:

  • 有点帮助,但没有太多的答案。我真的需要弄清楚如何在长时间运行的任务中将更新返回给网页,返回给用户。
【解决方案2】:

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 的精彩文章: Easy incremental status updates for long requests.

【讨论】:

    【解决方案3】:

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

    要测试这个理论,您可以尝试在 ProgressChanged 处理程序和 DoWork 处理程序中调用 Application.DoEvents(),看看是否有帮助。这是一个丑陋的解决方法,但如果调度程序同步运行您的任务,它应该强制 UI 更新。

    【讨论】:

    • 显然这是 Web 窗体,而不是 Windows 窗体。
    【解决方案4】:

    您基本上有两种选择。

    第一,您可以使用 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多