我想在c#应用程序中显示进度条。有一个功能,我在我的应用程序中按下按钮,这是耗时的,并且无法确定完成整个过程需要多少时间,因为我正在从Excel工作表中读取数据并存储到数据库还有那些东西。
当我点击按钮时,进度条应显示正确的状态,当整个过程完成时,我想显示“已成功完成”的消息。
AlertForm
StartConversion()
是我应用中的另一个表单,用于显示进度条
{{1}}方法是一种调用另一个方法的方法,该方法存在于实际执行耗时任务的类中。
我该如何完成这项任务?
答案 0 :(得分:1)
通常使用BackgroundWorker
它在一个单独的线程中运行,并提供工具来实现两个要求(更新进度信息,并在操作完成时执行)。您只需要创建BackgroundWorker
的实例并将其WorkerReportsProgress
- 属性设置为true
。
然后只需订阅符合您需求的event
:
DoWork
- 执行实际的长时间运行任务ProgressChanged
- 更新进度信息(例如,ProgressBar-value)RunWorkerCompleted
- 显示您的成功消息最后调用RunWorkerAsync
- 方法,你就完成了。
示例代码
var demoWorker = new BackgroundWorker { WorkerReportsProgress = true };
demoWorker.DoWork += (sender, args) =>
{
var worker = sender as BackgroundWorker;
if (sender == null) throw new Exception("Not a BackgroundWorker!");
foreach (var VARIABLE in COLLECTION)
{
// do your work
worker.ReportProgress(progressPercentage); // invokes the workers ProgressChanged-event
}
}
demoWorker.ProgressChanged += (sender, args) =>
{
this.progressBar.Value = args.ProgressPercentage;
};
demoWorker.RunWorkerCompleted += (sender, args) =>
{
// invoked when DoWork's eventhandler terminates
// show message
};
demoWorker.RunWorkerAsync(); // Invokes the workers DoWork-event
答案 1 :(得分:0)
您应该使用backgroundworker。
图像以下场景:
您有一个大约有1000行要处理的Excel文件。对于进度条,您可以假设10行是百分比。
时不时地在后台工作者中让它与主线程进行通信,说明已经处理了多少百分比。
backgroundworker有一个事件可以用来不时地填充你的进度条:
例如:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
var base = 100;
var counter = ExcelRows.Count;
var progressCounter = 0;
for (int i = 1; i <= ExcelRows.Count; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
//perform you action
MyRow.Save();
//report to the Progressbar
if(i % counter == 0)
worker.ReportProgress(progressCounter++);
}
}
}
// This event handler updates the progress.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MyProgress.Value = string.Format("{0}/100 %",e.ProgressPercentage);
}
答案 2 :(得分:0)
这样的一种方法是使用不同的线程使用backgroundworker。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializeBackgroundWorker();
}
private bool done = true;
int percentComplete = 1;
internal bool ImportData(IList<string> filenames)
{
try
{
// Long running task around 5 to 10 minutes
return true;
}
catch (Exception ex)
{
// returning true to break from th display progress loop
return true;
}
}
private void InitializeBackgroundWorker()
{
backgroundWorker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
backgroundWorker.ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
}
private void button1_Click(System.Object sender,System.EventArgs e)
{
//fd is Browse dialog to select files in my case
if (fd.ShowDialog() == DialogResult.OK)
{
var flist = fd.FileNames.ToList();
// Disable the Start button until the asynchronous operation is done.
this.startButton.Enabled = false;
if (!backgroundWorker.IsBusy)
{
this.Cursor = Cursors.WaitCursor;
backgroundWorker.RunWorkerAsync(flist);
}
else
{
backgroundWorker.CancelAsync();
}
}
}
private void DisplayProgress(BackgroundWorker worker)
{
try
{
percentComplete = 1;
while (done)
{
Thread.Sleep(500);
// Report progress
if (percentComplete == 100)
percentComplete = 1;
worker.ReportProgress(++percentComplete);
}
}
catch (Exception e)
{
}
}
// This event handler is where the actual,
// potentially time-consuming work is done.
private void backgroundWorker_DoWork(object sender,DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (worker.CancellationPending)
{
e.Cancel = true;
}
else
{
new Thread(() =>
{
DisplayProgress(worker);
}).Start();
done = ImportData((List<string>) e.Argument);
worker.ReportProgress(100);
e.Result = "Converted " + Path.GetFileName(((List<string>) e.Argument)[0]) + " successfully.";
}
}
// This event handler deals with the results of the background operation.
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
}
else
{
// Finally, handle the case where the operation succeeded.
listView.Items.Add(new ListViewItem(Text = e.Result.ToString()));
this.Cursor = Cursors.Arrow;
}
startButton.Text = "Start";
startButton.Enabled = true;
}
// This event handler updates the progress bar.
private void backgroundWorker_ProgressChanged(object sender,ProgressChangedEventArgs e)
{
this.progressBar.Value = e.ProgressPercentage;
}
}