ProgressBar зависает при использовании многопоточности - PullRequest
0 голосов
/ 08 января 2009

У меня есть ProgressBar, который использует стиль выделения при создании отчета. Я делаю это потому, что элемент управления ReportViewer, который я использую, занимает некоторое время для генерации отчета, поэтому форма не отвечает. Я создаю отчет, используя поток, чтобы ProgressBar мог показать, что программа работает. Однако когда я запускаю поток, ProgressBar зависает. Я уже пробовал BackgroundWorker, но это не сработало, поэтому я использовал свою собственную многопоточность.

Причина, по которой я использую метод Invoke (), заключается в том, что я не могу внести изменения в элемент управления ReportViewer в созданном мною потоке, поскольку он был создан в потоке пользовательского интерфейса.

Метод, который занимает больше всего времени, - это метод RefreshReport () элемента управления ReportViewer, поэтому я пытаюсь сделать это в своем собственном потоке вместо потока пользовательского интерфейса.

Любая помощь будет оценена. Спасибо.

Вот код для моей переменной потока:

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 ]

2 голосов
/ 08 января 2009

Ваш код начинает новый поток из потока пользовательского интерфейса. Затем новый поток немедленно маршалирует обратно в поток пользовательского интерфейса с помощью Invoke - так что, по сути, вы как будто не сделали его многопоточным.

Вместо этого заставьте новый поток выполнять всю фоновую обработку, которую он может, и направлять его обратно в пользовательский интерфейс только для тех частей процесса, которым необходимо обновить пользовательский интерфейс.

0 голосов
/ 08 января 2009

Вы можете попробовать использовать 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 или что-то в этом роде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...