0

アプリの起動中に、長いデータベースのアップグレードを行っています。それが始まる前に、進行状況バーのあるフォームを表示して、ユーザーが何かが起こっていることを認識し、待つ必要があることを確認します。

プログレスバーの再描画をブロックしないために、バックグラウンドワーカーでデータベースのアップグレードを行います。

コードは次のようになります。

            frmMain_Load(...)

            Dim wait As New frmWait
            wait.Show()

            Dim bw As New frmBWRebuildUserData
            bw.Start()
            Do While Not bw.Done
                System.Threading.Thread.Sleep(100)
            Loop

            'Okay, db update was done, now continue and show the main app window

私のfrmBWRebuildUserDataは次のようになります。

Public Class frmBWRebuildUserData

Private m_bDone As Boolean

Public ReadOnly Property Done() As Boolean

    Get
        Return m_bDone
    End Get

End Property

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

    modAppDB.RebuildUserDB()

End Sub
Public Sub Start()

    Me.BackgroundWorker1.RunWorkerAsync()

End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

    m_bDone = True

End Sub
End Class

しかし、60秒後、VB.NETは60秒以降メッセージがなかったことを通知します(このエラーを知っていると思います)。

しかし、バックグラウンドワーカーはそのような目的を意図しているので、私はここでかなり間違ったことをしていると思いますが、何を理解することはできません。

また、プログレスバーが再描画されていません。

誰か助けてもらえますか?どうもありがとうございます!

4

2 に答える 2

1

Backgroundworker は主に、DoWork 内にループがあるタスクに適しています。これにより、ループ内で UI フィードバックを行うことができます。DoWork が別のコマンドを呼び出すだけの場合、このコマンドが終了するまで待機し、その間は何もしません。それ以外では、BGW を使用しても、メイン スレッドがメッセージを処理し、ブロックされないようにすることができるため、ここで BGW を使用することは依然として完全に正しいと思います。
それとは別に、 yourbackgroundworker1は宣言されておらず、Steve が指摘したように、 Start()-Method には少なくともこの最初の行が必要です:
Addhandler Backgroundworker1.DoWork, AddressOf BackgroundWorker1_DoWork. RunworkerAsyncこれにより、が呼び出されたときに関数がトリガーされます。
スレッド通信の基本的な例 (およびそれに関連する基本的な問題) については、次の質問と回答をご覧ください。
プログレスバーとコードの場所 (vb.net) のマルチスレッド?
60秒の問題もわかりません。

于 2012-12-21T11:38:11.477 に答える
1

いくつかのこと。

バックグラウンド ワーカーには 60 秒のビルトイン タイムアウトはありません。したがって、それはあなたのコードにあるはずです。

なぜ backgroundWorker を使用し、コードにスリープ サイクルを導入するのですか? バックグラウンド ワーカーを使用して、長い操作の終了を待つことからユーザー インターフェイスを解放する必要があります。

バックグラウンド ワーカーは、進行状況をユーザー インターフェイス要素に報告するように求められたときに、次のようなものが必要です (C# で申し訳ありませんが、要点は理解できると思います)。

 backgroundworker.ProgressChanged += backgroundworker_ProgressChanged;
 backgroundworker.WorkerReportsProgress = true;

このシナリオでmodAppDB.RebuildUserDB()は、呼び出す必要があります

 backgroundworker.ReportProgress(percentComplete);

プログレスバーに伝えたいすべてのステップについて、もちろん、プログレスバーが表示されるフォームで ReportProgress 呼び出しによって発生したイベントをインターセプトする必要があります

private void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = (e.ProgressPercentage.ToString() + "%");
}
于 2012-12-21T10:19:14.990 に答える