在我的程序中[C#+ winforms]。我有进度条&列表显示。
通过一种方法我正在执行一些操作&然后更新Listview中的数据。添加的记录数是我为ProgressBar.value属性设置的值。我想要的是,根据进度条的值,它应该显示其进度。但是,进度条未更新。仅在方法执行结束时,进度条显示整个进度,即100%
在这方面有人可以帮助我吗?
谢谢, 阿米特
答案 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 page和MSDN Control.Invoke manual page以获取更多信息。
答案 3 :(得分:-1)
ProgressBar.Value必须介于0到100之间。
我猜你的问题是你正在更新GUI线程上的ListView。这意味着您需要在更改Application.DoEvents()
属性后调用ProgressBar.Value
。
最好在BackgroundWorker上运行并使用ProgressChanged
事件来处理ProgressBar
更新。
Here's another question关于同一主题。