在我的代码中,当单击一个按钮时,进度条设置为选取框,然后调用我的BackgroundWorker,但是当调用BackgroundWorker时,进度条会冻结或消失.我使用BackgroundWorker从UI线程中分离ReportViewer的RefreshRep
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问题是当你在RefreshReport()方法中调用.BeginInvoke()时. 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来锁定报表对象并防止重新进入.
现在,当你调用.BeginInvoke()时,报告过程开始了,但它根本没有阻塞,所以DoWork()方法没有任何东西可以做.它马上就回来了.此时BackgroundWorker认为已完成,因此调用.RunWorkerCompleted()方法,该方法将停止进度条.
根据评论,rvReport是一个可视化控件,而不是一个组件或简单的数据访问类.在这种情况下,您应该知道.Net中的可视控件不是线程安全的,因此不应该直接执行任何需要花费一些时间才能完成的操作.您在RefreshReport()方法中使用.BeginInvoke()跳过的箍具有在主UI线程中调用长时间运行的函数的效果.
要解决此问题,您需要关闭跨线程检查以便不抛出异常(简单但不推荐)或更改您使用控件的方式,以便主要工作在其他地方发生,并且控件只会引发事件时事情准备好了.如果你不能将控件修改到那个程度,那么它就是控件中的设计缺陷.