在我的程序 [C # + winforms] 中,我有进度条和列表视图。
通过一种方法,我执行一些操作,然后更新Listview中的数据。添加的记录数是我设置为ProgressBar.value属性的值。我希望在进度条的值上显示其进度。但是进度条没有得到更新。只有在方法执行结束时进度条才会显示整个进度即100%。
有人能帮助我吗?
谢谢,Amit
在我的程序 [C # + winforms] 中,我有进度条和列表视图。
通过一种方法,我执行一些操作,然后更新Listview中的数据。添加的记录数是我设置为ProgressBar.value属性的值。我希望在进度条的值上显示其进度。但是进度条没有得到更新。只有在方法执行结束时进度条才会显示整个进度即100%。
有人能帮助我吗?
谢谢,Amit
看起来你正在阻塞UI线程 - 也就是说,你没有释放系统完成任何绘制操作。
一种可行的方法是将 Application.DoEvents()
插入到你的代码中 - 但这很危险,并且存在重入等问题;而且这只是一个不太正规的方法。
更好的选择可能是在 BackgroundWorker
上进行处理,定期切换到UI线程更新内容(Control.Invoke)- 但如果你正在向 ListView
添加大量项目,则可能会比较棘手。
完整示例(尽管你可能想将UI更新批处理,而不是逐行更新):
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
class MyForm : Form
{
BackgroundWorker worker;
ListView list;
Button btn;
ProgressBar bar;
public MyForm()
{
Text = "Loader";
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.ProgressChanged += worker_ProgressChanged;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
list = new ListView();
list.Dock = DockStyle.Fill;
Controls.Add(list);
btn = new Button();
btn.Text = "Load";
btn.Dock = DockStyle.Bottom;
Controls.Add(btn);
btn.Click += btn_Click;
bar = new ProgressBar();
bar.Dock = DockStyle.Top;
Controls.Add(bar);
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btn.Enabled = true;
}
void btn_Click(object sender, EventArgs e)
{
worker.RunWorkerAsync();
btn.Enabled = false;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
string newRow = "Row " + i.ToString();
worker.ReportProgress(i, newRow);
Thread.Sleep(100);
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
list.Items.Add((string)e.UserState);
bar.Value = e.ProgressPercentage;
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
}
非常抱歉朋友们,
实际上,我给ProgressBar.value字段赋值时没有使用update()方法。我使用了它,我的问题得到了解决。
感谢大家的回复。
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;
}
}
ProgressBar.Value 必须在 0 和 100 之间。
我猜你的问题是你正在 GUI 线程上更新 ListView。这意味着在更改 ProgressBar.Value 属性后,你需要调用 Application.DoEvents()
。
最好在 BackgroundWorker 上运行,并使用 ProgressChanged
事件来处理 ProgressBar
更新。