Winforms进度条不更新(C#)

时间:2009-07-01 11:52:48

标签: c#

在我的程序中[C#+ winforms]。我有进度条&列表显示。

通过一种方法我正在执行一些操作&然后更新Listview中的数据。添加的记录数是我为ProgressBar.value属性设置的值。我想要的是,根据进度条的值,它应该显示其进度。但是,进度条未更新。仅在方法执行结束时,进度条显示整个进度,即100%

在这方面有人可以帮助我吗?

谢谢, 阿米特

4 个答案:

答案 0 :(得分:27)

听起来你正在阻止UI线程 - 也就是说你没有释放系统来做任何绘画。

一个hacky的答案是将Application.DoEvents()注入你的代码 - 但这是有风险的,并且有重新入侵等问题;它只是有点hacky。

更好的选择可能是在BackgroundWorker上进行处理,定期切换到UI线程来更新内容(Control.Invoke) - 但如果要向{添加大量项目,这可能会很棘手{1}}。

完整示例(尽管您可能希望批量处理UI更新 - 一次不是一行):

ListView

答案 1 :(得分:7)

真的很抱歉,

实际上,我正在为ProgressBar.value字段赋值,但没有使用update()方法。我用过&我的问题得到了解决。

感谢所有人的回复

答案 2 :(得分:3)

正如Marc所说,你想确保你创建一个新线程来进行长时间运行的计算。这样,每当您更改完成百分比时,用户界面线程(必须执行所有屏幕更新的线程)都可以重绘进度条。

值得注意的是, UI线程可以更新界面。因此,一旦你在一个单独的线程上运行,你必须经过一个额外的箍,以确保在UI线程上处理你的UI更改。如果您不确定正在运行什么线程,可以检查InvokeRequired的值(如果您的类是System.Windows.Form),以查看您是否在UI线程中是实际的。

要在UI线程上处理命令,请使用Control.Invoke()函数确保在您正在使用的控件的UI线程上处理更新。

在下面的示例代码中,我正在创建一个委托函数类型并提前声明调用的函数....我没有使用任何很酷的C#3.5函数,但我打赌你可以编写一个lamba表达式做同样的事情。

 private void bCreateInvoices_Click(object sender, EventArgs e)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(CreateInvoices);
        worker.RunWorkerAsync(this);
    }

 // Here is the long running function that needs to update the progress bar
 public void CreateInvoices(object sernder, DoWorkEventArgs e)
    {
        int totalChecked = CountCheckedServiceOrders();
        int totalCompleted = 0;

        foreach (...data to process...) {
            totalCompleted++;
            if (InvokeRequired) {
               Invoke(new Change(OnChange), "status text", 
                        totalCompleted, totalChecked);                
            }
        }
    }

    // this code updates the status while a background thread works
    private delegate void Change(string status, int complete, int total);
    private void OnChange(string status, int complete, int total)
    {
        if (status == null) {
            progressBar.Visible = false;
            lStatus.Text = "Task complete";
            progressBar.Value = 0;
        } else {
            progressBar.Visible = true;
            progressBar.Minimum = 0;
            progressBar.Maximum = total;
            progressBar.Value = complete;
            lStatus.Text = status;
        }

    }

请查看MSDN Control.InvokeRequired manual pageMSDN Control.Invoke manual page以获取更多信息。

答案 3 :(得分:-1)

ProgressBar.Value必须介于0到100之间。

我猜你的问题是你正在更新GUI线程上的ListView。这意味着您需要在更改Application.DoEvents()属性后调用ProgressBar.Value

最好在BackgroundWorker上运行并使用ProgressChanged事件来处理ProgressBar更新。

Here's another question关于同一主题。