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

      

0


source to share


2 answers


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.

+2


source


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.

0


source







All Articles