Marquee ProgressBar не отвечает с BackgroundWorker - PullRequest
4 голосов
/ 09 января 2009

В моем коде при нажатии кнопки индикатор выполнения устанавливается на выделение, а затем вызывается мой BackgroundWorker, но при вызове BackgroundWorker индикатор выполнения зависает или исчезает. Я использую BackgroundWorker для отделения метода RefreshReport ReportViewer от потока пользовательского интерфейса. Любая помощь приветствуется. Спасибо!

    Private Sub btnOtherReport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOtherReport.Click
        rvReport.ProcessingMode = ProcessingMode.Remote
        rvReport.ShowParameterPrompts = False
        rvReport.ServerReport.ReportServerUrl = New Uri("REPORT_SERVER_URL")
        rvReport.ServerReport.ReportPath = "REPORT_PATH"
        rvReport.BackColor = Color.White

        BackgroundWorker1.RunWorkerAsync()
    End Sub


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


    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        pbReports.Style = ProgressBarStyle.Blocks
        pbReports.Value = 100
    End Sub


    Public Sub RefreshReport()
        rvReport.BeginInvoke(New MethodInvoker(AddressOf rvReport.RefreshReport))
    End Sub

Ответы [ 2 ]

3 голосов
/ 09 января 2009

Проблема в том, что вы вызываете .BeginInvoke() в вашем RefreshReport() методе. Метод BackgroundWorker.DoWork() уже вызван в другом потоке, поэтому вы можете просто вызвать rvReport.RefreshReport(). Это должно выглядеть так:

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

Это действительно так просто, возможно добавление Monitor для блокировки объекта отчета и предотвращения повторного ввода.

Прямо сейчас, когда вы вызываете .BeginInvoke(), начинается процесс отчета, но он вообще не блокируется, поэтому для метода DoWork() ничего не остается. Это просто возвращается сразу. На этом этапе BackgroundWorker считает, что это сделано, поэтому вызывает метод .RunWorkerCompleted(), который останавливает индикатор выполнения.


На основании комментария rvReport - это визуальный элемент управления, а не компонент или простой класс доступа к данным. В этом случае вы должны знать, что визуальные элементы управления в .Net не являются поточно-ориентированными, и поэтому никогда не должен напрямую делать что-либо напрямую, для завершения которого требуется больше нескольких минут. Обручи, через которые вы прыгали с помощью .BeginInvoke() в методе RefreshReport(), вызывали вашу долгосрочную функцию в главном потоке пользовательского интерфейса .

Чтобы решить эту проблему, вам нужно либо отключить перекрестную проверку потоков, чтобы исключение не создавалось (просто, но не рекомендуется), либо изменить способ использования элемента управления, чтобы основная работа происходила в другом месте, а элемент управления просто вызывает события, когда все готово. Если вы не можете изменить элемент управления до такой степени, это недостаток дизайна в элементе управления.

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

Проблема в том, что индикатор выполнения не получает возможности перекрасить, пока фоновый процессор имеет процессор. Поэтому вам нужно вызвать System.Windows.Forms.Application.DoEvents () из основного ожидающего потока во время обработки. Это получит контроль и вызовет перерисовку индикатора выполнения.

Таким образом, после вызова BackgroundWorker1.RunWorkerAsync вы можете добавить цикл для вызова DoEvents, пока событие не будет сгенерировано, а затем вызвать событие в RunWorkerCompleted, чтобы позволить вызывающему коду завершиться. Поскольку это не позволяет основному коду продолжить работу, вы можете поместить вызов в фоновый вызов или в другой поток.

...