Pergunta

No meu código, quando um botão é clicado a barra de progresso está definido para marquise e depois o meu BackgroundWorker é chamado mas quando o BackgroundWorker é chamado congela barra de progresso ou desaparece. Eu uso o BackgroundWorker para separar o método RefreshReport do ReportViewer do segmento. Qualquer ajuda é apreciada. Obrigado!

    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
Foi útil?

Solução

O problema é quando você chamar .BeginInvoke() em seu método RefreshReport(). O método BackgroundWorker.DoWork() já é aumentada em um segmento diferente, então você pode apenas chamar rvReport.RefreshReport(). Deve olhar como este:

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

É realmente muito simples, com a possível adição de usar um Monitor para bloquear o objeto de relatório e prevenir a re-entrada.

Agora, quando você chamar .BeginInvoke() os pontapés processo relatório de fora, mas não bloquear em todos os portanto não há mais nada para o método DoWork() fazer. Ele só retorna imediatamente. Neste ponto, o BackgroundWorker pensa que está feito, então chama o método .RunWorkerCompleted(), que pára a sua barra de progresso.


Com base no comentário, rvReport é um controle visual, em vez de uma classe de acesso de dados componente ou simples. Nesse caso, você deve saber que os controles visuais em .Net não são thread-safe, e, portanto, deve não diretamente fazer diretamente qualquer coisa que leva mais do que alguns minutos para ser concluído. Os aros você estava pulando completamente com .BeginInvoke() no método RefreshReport() teve o efeito de chamar a função de longa duração no principal segmento interface do usuário .

Para resolver este problema, você precisa se quer desligar fio verificação cruzada para que a exceção não é lançada (simples, mas não recomendado) ou a mudança como você usa o controle, de modo que o trabalho principal acontece em outros lugares eo controle apenas gera eventos quando as coisas estão prontas. Se você não pode modificar o controle nessa medida, é uma falha de projeto no controle.

Outras dicas

O problema é que a barra de progresso não está sendo dada a oportunidade de pintar enquanto o thead fundo tem o processador. Então, você precisa chamar System.Windows.Forms.Application.DoEvents () do principal segmento de espera enquanto você está processando. Isto irá obter o controle e fazer com que a barra de progresso para repintar.

Assim, após o BackgroundWorker1.RunWorkerAsync chamar você pode adicionar um loop de DoEvents chamadas até que um evento é levantado e, em seguida, aumentar o evento em RunWorkerCompleted para deixar a saída código de chamada. Uma vez que este não permite que o código principal para continuar funcionando, você pode colocar a chamada na chamada fundo ou outro segmento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top