I want to show progress of calculations, which are performing in external library.
我想展示在外部库中执行的计算过程。
For example if I have some calculate method, and I want to use it for 100000 values in my Form class I can write:
例如,如果我有一些计算方法,我想用它来表示我的表单类中的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();
}
}
}
I should perform step after each calculation. But what if I perform all 100000 calculations in external method. When should I "perform step" if I don't want to make this method dependant on progress bar? I can, for example, write
我应该在每次计算后执行步骤。但是如果我用外部方法来计算所有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);
}
}
but I don't want to do like that.
但我不想那样做。
3 个解决方案
#1
88
I would suggest you have a look at BackgroundWorker. If you have a loop that large in your WinForm it will block and your app will look like it has hanged.
我建议你去看看背景工作人员。如果你的WinForm中有这么大的循环,它会阻塞,你的应用会看起来像挂起了一样。
Look at BackgroundWorker.ReportProgress()
to see how to report progress back to the UI thread.
查看BackgroundWorker.ReportProgress(),了解如何向UI线程报告进度。
For example:
例如:
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.
}
#2
31
Since .NET 4.5 you can use combination of async and await with Progress for sending updates to UI thread:
由于。net 4.5可以使用异步的组合,并等待向UI线程发送更新的进展:
private void Caluculate(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++)
{
Caluculate(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
}
Tasks are currently the preferred way to implement what BackgroundWorker
does.
任务是实现BackgroundWorker所做事情的首选方式。
Tasks and
Progress
are explained in more detail here:任务和进展在这里有更详细的解释:
- Async in 4.5: Enabling Progress and Cancellation in Async APIs
- 4.5中的异步:在异步api中启用进度和取消
- Reporting Progress from Async Tasks by Stephen Cleary
- Stephen Cleary报告异步任务的进度
- Task parallel library replacement for BackgroundWorker?
- 任务并行库替换BackgroundWorker?
#3
2
Hey there's a useful tutorial on Dot Net pearls: http://www.dotnetperls.com/progressbar
嘿,有一个关于Dot Net pearl的有用教程:http://www.dotnetperls.com/progressbar
In agreement with Peter, you need to use some amount of threading or the program will just hang, somewhat defeating the purpose.
与Peter一致,您需要使用一些线程,否则程序就会挂起,这在一定程度上违背了目的。
Example that uses ProgressBar and BackgroundWorker: C#
使用ProgressBar和BackgroundWorker: c#的例子。
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, System.EventArgs e)
{
// Start the BackgroundWorker.
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
// Wait 100 milliseconds.
Thread.Sleep(100);
// Report progress.
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
progressBar1.Value = e.ProgressPercentage;
// Set the text.
this.Text = e.ProgressPercentage.ToString();
}
}
}//closing here
#1
88
I would suggest you have a look at BackgroundWorker. If you have a loop that large in your WinForm it will block and your app will look like it has hanged.
我建议你去看看背景工作人员。如果你的WinForm中有这么大的循环,它会阻塞,你的应用会看起来像挂起了一样。
Look at BackgroundWorker.ReportProgress()
to see how to report progress back to the UI thread.
查看BackgroundWorker.ReportProgress(),了解如何向UI线程报告进度。
For example:
例如:
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.
}
#2
31
Since .NET 4.5 you can use combination of async and await with Progress for sending updates to UI thread:
由于。net 4.5可以使用异步的组合,并等待向UI线程发送更新的进展:
private void Caluculate(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++)
{
Caluculate(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
}
Tasks are currently the preferred way to implement what BackgroundWorker
does.
任务是实现BackgroundWorker所做事情的首选方式。
Tasks and
Progress
are explained in more detail here:任务和进展在这里有更详细的解释:
- Async in 4.5: Enabling Progress and Cancellation in Async APIs
- 4.5中的异步:在异步api中启用进度和取消
- Reporting Progress from Async Tasks by Stephen Cleary
- Stephen Cleary报告异步任务的进度
- Task parallel library replacement for BackgroundWorker?
- 任务并行库替换BackgroundWorker?
#3
2
Hey there's a useful tutorial on Dot Net pearls: http://www.dotnetperls.com/progressbar
嘿,有一个关于Dot Net pearl的有用教程:http://www.dotnetperls.com/progressbar
In agreement with Peter, you need to use some amount of threading or the program will just hang, somewhat defeating the purpose.
与Peter一致,您需要使用一些线程,否则程序就会挂起,这在一定程度上违背了目的。
Example that uses ProgressBar and BackgroundWorker: C#
使用ProgressBar和BackgroundWorker: c#的例子。
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, System.EventArgs e)
{
// Start the BackgroundWorker.
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
// Wait 100 milliseconds.
Thread.Sleep(100);
// Report progress.
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
progressBar1.Value = e.ProgressPercentage;
// Set the text.
this.Text = e.ProgressPercentage.ToString();
}
}
}//closing here