Use IProgress<T>
interface and Progress<T>
class.
async Task SomeAsynMethod(IProgress<double> progress)
{
double percentCompletedSoFar = 0;
while (!completed)
{
// your code here to do something
if (progress != null)
{
prgoress.Report(percentCompletedSoFar);
}
}
}
Here is how to use it in the calling code:
async Task SomeAsyncRoutine()
{
var progress = new Progress<double>();
progress.ProgressChanged += (sender, args) =>
{
// Update your progress bar and do whatever else you need
};
await SomeAsynMethod(progress);
}
Example
To run the following example, create a windows form application and add one Label
named label1
, one ProgressBar
named progressBar
and one Button
named button1
. In a real scenario, you would give your controls more meaningful names. Replace all of the code in your form with this code.
What this simple application does is:
When you press the button, it deletes "Progress.txt" file if it exists. It then calls SomeAsyncRoutine
. This routine creates an instance of Progress<double>
which implements IProgress<double>
interface. It subscribes to the ProgressChanged
event. It then calls SomeAsyncMethod(progress)
passing the instance progress
to it. When the progress is reported, it updates the progressBar1.Value
and it updates the label1.Text
property.
The SomeAsyncMethod
mimics some work. Using a loop starting at 1 and finishing at 100, it writes the loop variable (progress) to a file, sleeps for 100ms and then does the next iteration.
The progress to a file in the bin folder named "Progress.txt". Obviously in a real application you will do some meaningful work.
I kept the method names in the application the same as in the snippet I provided so it is easily mapped.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
File.Delete("Progress.txt");
await SomeAsyncRoutine();
}
async Task SomeAsynMethod(IProgress<double> progress)
{
double percentCompletedSoFar = 0;
bool completed = false;
while (!completed)
{
// your code here to do something
for (int i = 1; i <= 100; i++)
{
percentCompletedSoFar = i;
var t = new Task(() => WriteToProgressFile(i));
t.Start();
await t;
if (progress != null)
{
progress.Report(percentCompletedSoFar);
}
completed = i == 100;
}
}
}
private void WriteToProgressFile(int i)
{
File.AppendAllLines("Progress.txt",
new[] { string.Format("Completed: {0}%", i.ToString()) });
Thread.Sleep(100);
}
async Task SomeAsyncRoutine()
{
var progress = new Progress<double>();
progress.ProgressChanged += (sender, args) =>
{
// Update your progress bar and do whatever else you need
this.progressBar1.Value = (int) args;
this.label1.Text = args.ToString();
if (args == 100)
{
MessageBox.Show("Done");
}
};
await SomeAsynMethod(progress);
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…