使用多线程时,ProgressBar会冻结

时间:2009-01-08 17:53:55

标签: vb.net multithreading unresponsive-progressbar

我有一个ProgressBar,它在生成报告时使用选框样式。我之所以这样做是因为我使用的ReportViewer控件需要一些时间来生成报表,从而使表单无响应。我使用一个线程生成报告,因此ProgressBar可以显示该程序正在运行。但是,当我启动线程时,ProgressBar会冻结。我已经尝试过BackgroundWorker,但是没有用,所以我使用了自己的线程。

我使用Invoke()方法的原因是因为我无法在我创建的线程上对ReportViewer控件进行更改,因为它是在UI线程上创建的。

花费大部分时间处理的方法是ReportViewer控件的RefreshReport()方法,这就是我试图在自己的线程而不是UI线程上执行此操作的原因。

任何帮助将不胜感激。感谢。

以下是我的线程变量的代码:

Private t As New Thread(New ParameterizedThreadStart(AddressOf GenerateReport))

以下是生成报告的按钮的代码:

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

以下是生成报告的代码:

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

2 个答案:

答案 0 :(得分:2)

您的代码正在从UI线程启动一个新线程。然后新线程立即使用Invoke回调到UI线程 - 所以基本上就好像你根本没有使用多线程一样。

而不是这样,让新线程完成它可以进行的所有后台处理,并且只为需要更新UI的部分进程编组回UI。

答案 1 :(得分:0)

您可以尝试使用ThreadPool生成新的工作线程。我在WPF应用程序中使用下面的代码来显示超过4秒左右的任何内容的加载屏幕。

您可能需要更改一些语法,因为我是C#家伙......

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

另外,我相信Dispatcher.BeginInvoke仅在WPF中,而不在WinForms中,所以我需要将其更改回Me.Invoke或其他内容。