Marquee ProgressBar que não respondem com BackgroundWorker
-
06-07-2019 - |
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
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.