代码之家  ›  专栏  ›  技术社区  ›  Bryan Roth

Marquee ProgressBar对BackgroundWorker没有响应

  •  4
  • Bryan Roth  · 技术社区  · 17 年前

    在我的代码中,当单击一个按钮时,进度条被设置为选框,然后调用我的BackgroundWorker,但当调用BackgroundWorker时,进度条冻结或消失。我使用BackgroundWorker将ReportViewer的RefreshReport方法与UI线程分离。感谢您的帮助。谢谢!

        Private Sub btnOtherReport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOtherReport.Click
            rvReport.ProcessingMode = ProcessingMode.Remote
            rvReport.ShowParameterPrompts = False
            rvReport.ServerReport.ReportServerUrl = New Uri("REPORT_SERVER_URL")
            rvReport.ServerReport.ReportPath = "REPORT_PATH"
            rvReport.BackColor = Color.White
    
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
    
        Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            RefreshReport()
        End Sub
    
    
        Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
            pbReports.Style = ProgressBarStyle.Blocks
            pbReports.Value = 100
        End Sub
    
    
        Public Sub RefreshReport()
            rvReport.BeginInvoke(New MethodInvoker(AddressOf rvReport.RefreshReport))
        End Sub
    
    2 回复  |  直到 17 年前
        1
  •  3
  •   Joel Coehoorn    17 年前

    问题是你打电话的时候 .BeginInvoke() 在你 RefreshReport() 方法。这个 BackgroundWorker.DoWork() 方法已在其他线程中引发,因此您可以只调用 rvReport.RefreshReport() . 它应该是这样的:

    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        rvReport.RefreshReport()
    End Sub
    

    这真的很简单,除了使用 Monitor 锁定报表对象并防止重新输入。

    现在,当你打电话的时候 开始调用() 报告过程开始了,但根本没有阻塞,因此 DoWork() 方法去做。它马上就回来了。在这一点上,后台工作人员认为已经完成了,所以称 .RunWorkerCompleted() 方法,停止进度条。


    根据评论, rvReport 是可视控件,而不是组件或简单数据访问类。在这种情况下,您应该知道.NET中的可视化控件不是线程安全的,因此应该 从未 直接做任何需要几分钟以上才能完成的事情。你用的篮球 开始调用() 在 刷新报告() 方法具有调用长时间运行函数的效果 在主UI线程中 .

    要解决此问题,您需要关闭跨线程检查,以便不引发异常(简单,但不推荐),或者更改使用控件的方式,以便在其他地方执行主工作,并且控件只在准备就绪时引发事件。如果您不能在这种程度上修改控件,这是控件中的一个设计缺陷。

        2
  •  -1
  •   Marcus Erickson    17 年前

    问题是,当后台thead有处理器时,进度条没有机会重新绘制。因此,您需要在处理过程中从主等待线程调用System.Windows.Forms.Application.DoEvents()。这将得到控制并导致进度条重新绘制。

    因此,在backgroundworker1.runworkerasync调用之后,可以添加一个循环来调用doEvents,直到引发一个事件,然后在runworkercompleted中引发该事件,以退出调用代码。因为这不允许主代码继续运行,所以可以将调用放在后台调用或其他线程中。