Reputation: 29427
I have used in the past the BackgroundWorker
in a Windows Form application.
For my new exercise I need to use async
methods inside the worker and I am getting a little bit confused about that.
This is my code structure. In the form load event I am creating the BackgroundWorker
object and setup events
private void fMain_Load( object sender, EventArgs e ) {
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler( bw_DoWork );
bw.ProgressChanged += new ProgressChangedEventHandler( bw_ProgressChanged );
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler( bw_RunWorkerCompleted );
}
When the user click a button I am starting the worker
private void btnGenerate_Click( object sender, EventArgs e ) {
Settings settings = new Settings();
pbCounter.Visible = true;
btnGenerate.Enabled = false;
bw.RunWorkerAsync( settings );
}
And this is the worker code
private async void bw_DoWork( object sender, DoWorkEventArgs e ) {
try {
for ( int ix = 1; i <= 100; i++ ) {
using (var client = new HttpClient()) {
[???? how to call and wait here ????]
HttpResponseMessage response = await client.PostAsync( "endpoint", new StringContent( JsonConvert.SerializeObject( formContent ), Encoding.UTF8, "application/json" ) );
}
//The counter will keep track of your process
Application.DoEvents();
int percentage = ix * 100 / settings.TotalRuns;
bw.ReportProgress( percentage );
}
}
catch ( Exception ex ) {
MessageBox.Show( ex.Message, "Gift Creator", MessageBoxButtons.OK, MessageBoxIcon.Error );
}
}
Upvotes: 0
Views: 1777
Reputation: 43886
If you use async
and await
there is no need for a background worker. In fact, your background worker would not work because the control is given back to the caller when you use await
. And when the DoWork
handler returns control to its caller, the background worker will terminate and not continue its remainnig tasks.
So I would make the button handler async
and do the http requests there:
private async void btnGenerate_Click(object sender, EventArgs e)
{
const int totalRuns = 5;
pbCounter.Visible = true;
pbCounter.Minimum = 0;
pbCounter.Maximum = totalRuns;
pbCounter.Value = 0;
btnGenerate.Enabled = false;
try
{
for ( int i = 1; i <= totalRuns; i++ )
{
using (var client = new HttpClient())
await client.PostAsync( "endpoint", new StringContent( JsonConvert.SerializeObject( formContent ), Encoding.UTF8, "application/json" ) );
pbCounter.Value = i;
}
}
catch (Exception ex )
{
MessageBox.Show( ex.Message, "Gift Creator", MessageBoxButtons.OK, MessageBoxIcon.Error );
}
btnGenerate.Enabled = true;
}
So this handler gives back the control to the caller (to say it over-simplified: the UI) while waiting for the http request. When the request is finished, the execution is continued at the pbCounter.Value = i
line - and on the UI thread! So you can safely update the progress bar, because you're not doing it from another thread.
I hope this helps you. Note that I set the pbCounter.Maximum
to the number of loops you're about to run, so you don't need to calculate the percentage.
Upvotes: 2