使用HttpClient异步方法的BackgroundWorker [英] BackgroundWorker that uses HttpClient async methods
问题描述
我过去在Windows Form应用程序中使用过 BackgroundWorker
.对于我的新练习,我需要在worker内部使用 async
方法,对此我有些困惑.
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.
这是我的代码结构.在表单加载事件中,我正在创建 BackgroundWorker
对象和设置事件
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 );
}
这是工作人员代码
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 );
}
}
推荐答案
如果使用 async
和 await
,则不需要后台工作程序.实际上,您的后台工作者将无法工作,因为当您使用 await
时,控制权将交还给调用者.并且,当 DoWork
处理程序将控制权返回给其调用者时,后台工作程序将终止并且不继续其剩余任务.
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.
因此,我将使按钮处理程序 async
并在那里执行http请求:
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;
}
因此,该处理程序在等待http请求时将控制权交还给调用方(说得过于简单:UI).请求完成后,将在 pbCounter.Value = i
行和UI线程上继续执行!这样您就可以安全地更新进度条,因为您不是从另一个线程执行的.
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.
希望这对您有所帮助.请注意,我将 pbCounter.Maximum
设置为要运行的循环数,因此您无需计算百分比.
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.
这篇关于使用HttpClient异步方法的BackgroundWorker的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!