ProgressBar hangs when using multithreading
I have a ProgressBar that uses the marquee style when generating a report. The reason I am doing this is because the ReportViewer control I am using takes a while to generate the report, thus making the form unresponsive. I am generating a report using a stream, so the ProgressBar can show that the program is running. However, when I start the thread, the ProgressBar hangs. I already tried BackgroundWorker but it didn't work, so I used my own threading.
The reason I am using the Invoke () method is because I cannot make changes to the ReportViewer control on the created thread, because it was created on the UI thread.
The method that takes most of the time is the RefreshReport () method of the ReportViewer control, so I am trying to do this on my thread, not the UI thread.
Any help would be greatly appreciated. Thank.
Here is the code for my stream variable:
Private t As New Thread(New ParameterizedThreadStart(AddressOf GenerateReport))
Here is the code for the button that generates the report:
Private Sub btnGenerateReport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerateReport.Click
pbReports.Style = ProgressBarStyle.Marquee
If t.ThreadState = ThreadState.Unstarted Then
t.IsBackground = True
t.Start(ReportType.Roads)
ElseIf t.ThreadState = ThreadState.Stopped Then
t = Nothing
t = New Thread(New ParameterizedThreadStart(AddressOf GenerateReport))
t.IsBackground = True
t.Start(ReportType.Roads)
End If
End Sub
Here is the code that generates the report:
Public Sub GenerateReport(ByVal rt As ReportType)
If rvReport.InvokeRequired Then
Dim d As New GenerateReportCallBack(AddressOf GenerateReport)
Me.Invoke(d, New Object() {rt})
Else
rvReport.ProcessingMode = ProcessingMode.Remote
rvReport.ShowParameterPrompts = False
rvReport.ServerReport.ReportServerUrl = New Uri("My_Report_Server_URL")
rvReport.ServerReport.ReportPath = "My_Report_Path"
rvReport.BackColor = Color.White
rvReport.RefreshReport()
End If
If pbReports.InvokeRequired Then
Dim d As New StopProgressBarCallBack(AddressOf StopProgressBar)
Me.Invoke(d)
Else
StopProgressBar()
End If
End Sub
source to share
Your code starts a new thread from the UI thread. The new thread is then immediately dispatched back to the UI thread using Invoke - so it's basically as if you weren't making it multithreaded at all.
Instead, make a new thread doing all the background processing, and only marshal back to the UI for the parts of the process that need to update the UI.
source to share
You can try using ThreadPool to create a new worker thread. I am using below in a WPF application to show the loading screen for anything that takes over 4 seconds.
You may need to change some syntax as I am a C # guy ...
Private Sub btnGenerateReport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerateReport.Click
pbReports.Style = ProgressBarStyle.Marquee
ThreadPool.QueueUserWorkItem(Function(th) Do
GenerateReport(ReportType.Roads)
Dispatcher.BeginInvoke(DispatcherPriority.Normal, DirectCast(Function() Do
StopProgressBar()
End Function, Action)
End Function)
End Sub
Also, I believe Dispatcher.BeginInvoke only works in WPF, not WinForms, so you need to change that to Me.Invoke or something.
source to share