Marquee ProgressBar unresponsive with BackgroundWorker

非 Y 不嫁゛ 提交于 2019-12-05 17:47:42

The problem is when you call .BeginInvoke() in your RefreshReport() method. The BackgroundWorker.DoWork() method is already raised in a different thread, so you can just call rvReport.RefreshReport(). It should look like this:

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

It really is that simple, with the possible addition of using a Monitor to lock your report object and prevent re-entry.

Right now, when you call .BeginInvoke() the report process kicks off, but it doesn't block at all so there's nothing left for the DoWork() method to do. It just returns right away. At this point the BackgroundWorker thinks it's done, so calls the .RunWorkerCompleted() method, which stops your progress bar.


Based on the comment, rvReport is a visual control rather than a component or simple data access class. In that case, you should know that visual controls in .Net are not thread safe, and therefore should never directly do anything directly that takes more than a few moments to complete. The hoops you were jumping through with .BeginInvoke() in the RefreshReport() method had the effect of calling your long running function in the main UI thread.

To solve this problem, you need to either turn off cross thread checking so that the exception is not thrown (simple, but not recommended) or change how you use the control, so that the main work happens elsewhere and the control just raises events when things are ready. If you can't modify the control to that extent, it's a design flaw in the control.

The problem is that the progress bar is not being given a chance to repaint while the background thead has the processor. So you need to call System.Windows.Forms.Application.DoEvents() from the main waiting thread while you are processing. This will get control and cause the progress bar to repaint.

So after the BackgroundWorker1.RunWorkerAsync call you can add a loop to call DoEvents until an event is raised and then raise the event in RunWorkerCompleted to let the calling code exit. Since this doesnt allow the main code to continue running you could put the call in the Background call or another thread.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!