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 proc 之前,我将 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 已解冻并将栏更新为可见

然后这个:

  • ==>新线程运行肉类向UI线程发送更新,以便进度条可以更新

然后这个:

  • 新线程结束并在其最终方法中设置不可见
  • UI 代码已完成,因此 UI 已解冻并将栏更新为不可见

TaskBackgroundworker应该很容易实现这一点。

更新代码以显示恒定滚动

我相信您只是缺少进度条的样式应该是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 代码从数据库中获取 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 回答