Pregunta

En mi código, cuando se hace clic en un botón, la barra de progreso se establece en un recuadro y luego se llama a mi BackgroundWorker, pero cuando se llama a BackgroundWorker, la barra de progreso se congela o desaparece. Utilizo el BackgroundWorker para separar el método RefreshReport del ReportViewer del hilo de la interfaz de usuario. Cualquier ayuda es apreciada. Gracias!

    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
¿Fue útil?

Solución

El problema es cuando llama a .BeginInvoke () en su método RefreshReport () . El método BackgroundWorker.DoWork () ya está generado en un hilo diferente, por lo que puede llamar a rvReport.RefreshReport () . Debería verse así:

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

Realmente es así de simple, con la posible adición de usar un Monitor para bloquear su objeto de informe y evitar el reingreso.

En este momento, cuando llama a .BeginInvoke () , el proceso de informe se inicia, pero no se bloquea en absoluto, por lo que no queda nada para el DoWork () Método para hacer. Simplemente regresa de inmediato. En este punto, BackgroundWorker cree que está hecho, por lo que llama al método .RunWorkerCompleted () , que detiene su barra de progreso.


Según el comentario, rvReport es un control visual en lugar de un componente o una clase de acceso a datos simple. En ese caso, debe saber que los controles visuales en .Net no son seguros para subprocesos y, por lo tanto, nunca deben hacer directamente cualquier cosa que tarde más de unos minutos en completarse. Los aros por los que saltabas con .BeginInvoke () en el método RefreshReport () tuvieron el efecto de llamar a tu función de ejecución larga en el hilo principal de la interfaz de usuario .

Para resolver este problema, debe desactivar la comprobación de subprocesos cruzados para que no se genere la excepción (simple, pero no recomendado) o cambiar la forma en que usa el control, de modo que el trabajo principal ocurra en otro lugar y el control simplemente plantea eventos cuando las cosas están listas. Si no puede modificar el control hasta ese punto, es un defecto de diseño en el control.

Otros consejos

El problema es que la barra de progreso no tiene la oportunidad de volver a pintar mientras el procesador de fondo tiene el procesador. Por lo tanto, debe llamar a System.Windows.Forms.Application.DoEvents () desde el hilo de espera principal mientras procesa. Esto obtendrá el control y hará que la barra de progreso se vuelva a pintar.

Entonces, después de la llamada BackgroundWorker1.RunWorkerAsync, puede agregar un bucle para llamar a DoEvents hasta que se genere un evento y luego generar el evento en RunWorkerCompleted para permitir que salga el código de llamada. Como esto no permite que el código principal continúe ejecutándose, puede colocar la llamada en la llamada en segundo plano u otro hilo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top