1

表示され、クエリが実行されていることを示す「アクティビティ」を示す非決定論的なプログレスバーが必要です。クエリが完了すると、非表示に戻ります。十分に単純に思えます。しかし、このコードでは:

try
{
    Cursor.Current = Cursors.WaitCursor;
    progressBarChanges.Value = 50;
    progressBarChanges.Step = 20;
    progressBarChanges.Visible = true;
    ... // the meat of the code, where the query is being done, elided
} finally
{
    progressBarChanges.Visible = false;
    Cursor.Current = Cursors.Default;
}

...クエリの実行に時間がかかる場合でも、進行状況バーは表示されません。プログレス バーは DGV にあります。私の進行状況コードが少し不自由であることはわかっていますが、まず最初に、まず最初に何かを表示したいだけです。

アップデート

クエリを実行する BackgroundWorker プロシージャを呼び出す前に、progressBar を目に見えるように設定しています。

progressBarChanges.Value = 50;
progressBarChanges.Step = 20;
progressBarChanges.Visible = true;
. . .    
if (args.KeyCode == Keys.Enter)
{
    if (ValidEntryForCRID(textBoxID.Text))
    {
        RetrieveAndBindPlatypusData();
        var tb = (TextBox)Controls.Find("textBoxDuckbill", true).First();
        if (tb != null)
        {
            tb.Focus(); 
        }
        if ((!string.IsNullOrWhiteSpace(textBoxID.Text)) &&
            (backgroundWorkerShowChanges.IsBusy != true))
        {
            backgroundWorkerShowChanges.RunWorkerAsync();
        }
    . . .

...まだ、progressBar が表示されることはありません (DGV の DataSource に返されたクエリ/結果セットの OracleDateTable 値が割り当てられた後に、visible = false に戻さない限り)。私がそれをコメントアウトすると、(遅ればせながら) ついに現れ、どうやら (誤って) 「遅くなるよりはましだ」と考えているようです。

Windowsに「progressBarChanges.Visible = true;」に「注意を払う」よう強制する方法はありますか? すぐにライン?.ProcessMessages() または this.Refresh または ...??? のようなもの

4

2 に答える 2

7

これは、UI スレッドを更新する時間を与えていないために発生しています。コードを表示してすぐに実行するように更新しています。コードはバックグラウンド スレッドで実行され、更新メッセージを送信する必要があります。

詳しく説明するには:

Visible プロパティを設定すると、UI スレッドは現在のロジックが終了するまで実際には更新されません。それで、何が起こっているかは次のとおりです。

  • 見える
  • 実行プロセス
  • 見えない
  • コードが完成したので、UI の凍結が解除されて更新されました...最後の状態は非表示です

あなたが望むものは:

  • 見える
  • 肉を実行するために新しいスレッドを開始します
  • UI コードが完成したため、UI の凍結が解除され、バーが Visible に更新されます

次に、これ:

  • ==>プログレスバーが更新できるように、新しいスレッドが肉を実行してUIスレッドに更新を送信します

次に、これ:

  • 新しいスレッドが終了し、最終的なメソッド セットで非表示
  • UI コードが完成したため、UI の凍結が解除され、バーが非表示に更新されます

TaskまたはBackgroundworkerは、これを実装するのが非常に簡単なはずです。

一定のスクロールを表示するためのコードの更新

プログレスバーのスタイルがProgressBarStyle.Marquee. すでに作業をバックグラウンドワーカーにオフロードしている場合、残りはそのまま機能するはずです

    public Form1()
    {
        InitializeComponent();
        this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
        this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
        progressBar1.Enabled = progressBar1.Visible = false;
        progressBar1.Style = ProgressBarStyle.Marquee;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        progressBar1.Visible = true;
        progressBar1.Enabled = true;
        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        System.Threading.Thread.Sleep(10000);
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        progressBar1.Visible = progressBar1.Enabled = false;
    }
于 2012-10-12T18:54:58.100 に答える
0

これが私がそれを機能させる方法です:

BackgroundWorker 呼び出しの直前に ProgressBar を有効にします。

progressBarChanges.Visible = true;
backgroundWorkerShowChanges.RunWorkerAsync();

BackgroundWorker コードは、DB から OracleDataTable を取得します。

private void backgroundWorkerShowChanges_DoWork(object sender, System.ComponentModel.DoWorkEventArgs args)
{
    holdChanges = GetChangesMade(textBoxID.Text);
}

BackgroundWorker の「完了」イベントは、UI を更新します。

private void backgroundWorkerShowChanges_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs args)
{
    PopulateChangesGrid();
}

PopulateChangesGrid() で、OracleDataTable オブジェクトを DGV に割り当てた後、進行状況バーを非表示に設定しました。

private void PopulateChangesGrid()
{
    dgvPlatypi.DataSource = holdChanges;
    progressBarChanges.Visible = false;
}

それはチャームのように機能します (<-必ずしも Windows 8 の「Metro」チャームへの参照ではありません)。

于 2012-10-12T21:34:44.550 に答える