在c#中使用进度条
本文关键字: | 更新日期: 2023-09-27 18:02:28
我想在我的c#应用程序中显示一个进度条。有一个函数,我调用按钮点击在我的应用程序,这是耗时的,它是不可能确定需要多少时间来完成整个过程,因为我正在从Excel表读取数据和存储到数据库和所有的东西。
当我点击按钮时,进度条应该显示正确的状态,当整个过程完成时,我想显示"完成成功"的消息。
AlertForm alert;
private void btnImport_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy != true)
{
// create a new instance of the alert form
alert = new AlertForm();
// event handler for the Cancel button in AlertForm
alert.Canceled += new EventHandler<EventArgs>(buttonCancel_Click);
alert.Show();
backgroundWorker1.RunWorkerAsync();
StartConversion(txtPath.Text.Trim(), Path.GetFileName(txtPath.Text.Trim()));
}
}
#region Progress bar EVENTS
private void buttonStart_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy != true)
{
// create a new instance of the alert form
alert = new AlertForm();
// event handler for the Cancel button in AlertForm
alert.Canceled += new EventHandler<EventArgs>(buttonCancel_Click);
alert.Show();
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();
}
}
// This event handler cancels the backgroundworker, fired from Cancel button in AlertForm.
private void buttonCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation == true)
{
// Cancel the asynchronous operation.
backgroundWorker1.CancelAsync();
// Close the AlertForm
alert.Close();
}
}
// This event handler is where the time-consuming work is done.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
worker.ReportProgress(i * 10);
System.Threading.Thread.Sleep(500);
}
}
}
// This event handler updates the progress.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Show the progress in main form (GUI)
labelResult.Text = (e.ProgressPercentage.ToString() + "%");
// Pass the progress to AlertForm label and progressbar
alert.Message = "In progress, please wait... " + e.ProgressPercentage.ToString() + "%";
alert.ProgressValue = e.ProgressPercentage;
}
// This event handler deals with the results of the background operation.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
labelResult.Text = "Canceled!";
}
else if (e.Error != null)
{
labelResult.Text = "Error: " + e.Error.Message;
}
else
{
labelResult.Text = "Done!";
}
// Close the AlertForm
alert.Close();
}
#endregion
AlertForm
是我的应用程序中的另一个表单,用于显示进度条StartConversion()
方法是调用另一个方法的方法,该方法存在于实际执行耗时任务的类中。
我如何完成这个任务?
通常使用BackgroundWorker
它运行在一个单独的线程中,并提供工具来实现您的两个需求(更新进度信息,并在操作完成时执行其他操作)。您只需要创建一个BackgroundWorker
实例并将其WorkerReportsProgress
-属性设置为true
。
然后只需订阅相应需求的 event
s:
-
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
你应该使用后台worker。
想象以下场景:
您有一个大约有1000行要处理的excel文件。对于进度条,可以假设10行是一个百分比。
在backgroundworker中,你让它时不时地与主线程通信,说明已经处理了多少百分比。
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);
}
这样的方法是使用不同的线程使用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;
}
}