4

私のコードでは、ボタンをクリックすると進行状況バーがマーキーに設定され、BackgroundWorker が呼び出されますが、BackgroundWorker が呼び出されると進行状況バーがフリーズまたは非表示になります。BackgroundWorker を使用して、ReportViewer の RefreshReport メソッドを UI スレッドから分離します。どんな助けでも大歓迎です。ありがとう!

    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
4

2 に答える 2

3

.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()メソッドでジャンプしていたフープは、メインUIスレッドでRefreshReport()長時間実行されている関数を呼び出す効果がありました。

この問題を解決するには、例外がスローされないようにクロススレッドチェックをオフにするか(単純ですが、推奨されません)、コントロールの使用方法を変更して、メインの作業が他の場所で行われ、コントロールが次の場合にイベントを発生させるようにする必要があります。物事は準備ができています。その程度までコントロールを変更できない場合は、コントロールの設計上の欠陥です。

于 2009-01-09T19:37:30.210 に答える
-1

問題は、背景の広告にプロセッサがある間、プログレス バーに再描画の機会が与えられないことです。そのため、処理中にメインの待機スレッドから System.Windows.Forms.Application.DoEvents() を呼び出す必要があります。これにより制御が取得され、プログレス バーが再描画されます。

したがって、BackgroundWorker1.RunWorkerAsync 呼び出しの後に、イベントが発生するまで DoEvents を呼び出すループを追加し、RunWorkerCompleted でイベントを発生させて、呼び出し元のコードを終了させることができます。これではメイン コードを実行し続けることができないため、呼び出しをバックグラウンド呼び出しまたは別のスレッドに入れることができます。

于 2009-01-09T19:09:22.093 に答える