简单的BackgroundWorker不会更新网页上的标签

我在这个有用的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(); 

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

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

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

     

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("", PercentComplete, Message)); Response.Flush(); } 

您可以在这里看到结果并阅读更多Dave Ward的精彩文章: 长期请求的简单增量状态更新。

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

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

你基本上有两个选择。

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