Вопрос

В моем коде при нажатии кнопки индикатор выполнения устанавливается на выделение, а затем вызывается мой 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
Это было полезно?

Решение

Проблема в том, что вы вызываете .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 () , вызывали долгосрочную функцию в основном потоке пользовательского интерфейса .

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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top