Dmy*_*tro 92 c# winforms progress-bar
我想显示在外部库中执行的计算进度.
例如,如果我有一些计算方法,并且我想在我的Form类中使用它为100000个值,我可以写:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Caluculate(int i)
{
double pow = Math.Pow(i, i);
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Maximum = 100000;
progressBar1.Step = 1;
for(int j = 0; j < 100000; j++)
{
Caluculate(j);
progressBar1.PerformStep();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我应该在每次计算后执行步骤.但是,如果我在外部方法中执行所有100000计算,该怎么办?如果我不想让这个方法依赖于进度条,我什么时候应该"执行步骤"?例如,我可以写
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void CaluculateAll(System.Windows.Forms.ProgressBar progressBar)
{
progressBar.Maximum = 100000;
progressBar.Step = 1;
for(int j = 0; j < 100000; j++)
{
double pow = Math.Pow(j, j); //Calculation
progressBar.PerformStep();
}
}
private void button1_Click(object sender, EventArgs e)
{
CaluculateAll(progressBar1);
}
}
Run Code Online (Sandbox Code Playgroud)
但我不想这样做.
Pet*_*hie 110
我建议你看看BackgroundWorker.如果你的WinForm中有一个很大的循环,它会阻塞,你的应用程序看起来会被挂起.
查看BackgroundWorker.ReportProgress()如何将进度报告回UI线程.
例如:
private void Calculate(int i)
{
double pow = Math.Pow(i, i);
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Maximum = 100;
progressBar1.Step = 1;
progressBar1.Value = 0;
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
var backgroundWorker = sender as BackgroundWorker;
for (int j = 0; j < 100000; j++)
{
Calculate(j);
backgroundWorker.ReportProgress((j * 100) / 100000);
}
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// TODO: do something with final calculation.
}
Run Code Online (Sandbox Code Playgroud)
qua*_*oft 66
从.NET 4.5开始,您可以结合使用async和await with Progress来向UI线程发送更新:
private void Calculate(int i)
{
double pow = Math.Pow(i, i);
}
public void DoWork(IProgress<int> progress)
{
// This method is executed in the context of
// another thread (different than the main UI thread),
// so use only thread-safe code
for (int j = 0; j < 100000; j++)
{
Calculate(j);
// Use progress to notify UI thread that progress has
// changed
if (progress != null)
progress.Report((j + 1) * 100 / 100000);
}
}
private async void button1_Click(object sender, EventArgs e)
{
progressBar1.Maximum = 100;
progressBar1.Step = 1;
var progress = new Progress<int>(v =>
{
// This lambda is executed in context of UI thread,
// so it can safely update form controls
progressBar1.Value = v;
});
// Run operation in another thread
await Task.Run(() => DoWork(progress));
// TODO: Do something after all calculations
}
Run Code Online (Sandbox Code Playgroud)
任务目前是实现目标的首选方式BackgroundWorker.
任务并
Progress在此处详细说明:
- 4.5中的异步:在异步API中启用进度和取消
- Stephen Cleary 报告异步任务的进展情况
- BackgroundWorker的任务并行库替换?