【问题标题】:Progress bar never displays进度条从不显示
【发布时间】:2012-10-12 18:52:27
【问题描述】:

我只是想要一个不确定的进度条,它变得可见并显示一些“活动”以指示查询正在运行,然后,当查询通过时,它又回到不可见状态。看起来很简单;但使用此代码:

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 上。我意识到我的进度代码有点蹩脚,但首先要做的是 - 我只想让该死的东西向初学者展示 something

更新

在调用运行查询的 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 或...???

【问题讨论】:

  • 你记得开启进度条吗?
  • 你为什么使用progressBarChanges.PerformStep();
  • 您可能必须在线程中执行该操作 - 否则您会用您的“肉”阻塞 UI 线程。
  • @Desolator:出于绝望。
  • @BDJ:默认启用(在设计时),我不会更改它。

标签: c# winforms progress-bar


【解决方案1】:

发生这种情况是因为您没有给 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;
    }

【讨论】:

  • 我已经在使用 BackgroundWorker 进行查询;我也尝试将 Visible = true,false 代码放在那里...
  • 我认为您的意思是“...将栏更新为不可见”,位于第一组要点的第三个要点中。
  • 无论如何,对于本应如此简单的事情来说,这似乎 糟糕(我的意思是 糟糕)复杂:1)显示一个进步栏疯狂旋转(或做跳跃千斤顶或其他) 2)在进度条“运行”时运行查询 3)当查询返回并使用结果集更新 GUI 时,进度条为 86。
  • 好的,我开始工作了——结果很简单。我将在上面发布我的步骤,附加到我的原始帖子中。
  • 再三考虑,我将其添加为答案。
【解决方案2】:

这就是我让它工作的方式:

我在 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;
}

它就像一个魅力(

【讨论】:

  • 这是解决问题的正确/预期方法。贾斯汀可能对你的术语感到困惑。他提供了有关使用进度条的说明,该进度条指示已完成多少任务以及您还需要走多远。您想要一个忙碌的栏或忙碌的微调器,它表明您的应用程序正在运行,而没有任何迹象表明已经完成了多少工作或需要多少工作。
  • @Trisped 你是对的,我不同意这是解决这个问题的正确方法......进度条有一个样式“选框”,不需要这样的样板代码就可以做到这一点。跨度>
  • 好吧,我确实说过“不确定性”。不过,这是对 Marquee 风格的一个很好的提示 - 使用它我必须 86 "progressBarChanges.PerformStep();"
猜你喜欢
  • 1970-01-01
  • 2016-09-13
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多