使用 HttpClient 异步方法的 BackgroundWorker
BackgroundWorker that uses HttpClient async methods
我过去曾在 Windows 表单应用程序中使用过 BackgroundWorker
。
对于我的新练习,我需要在 worker 中使用 async
方法,对此我有点困惑。
这是我的代码结构。在表单加载事件中,我正在创建 BackgroundWorker
对象和设置事件
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 );
}
当用户点击一个按钮时,我将启动 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
处理程序 returns 控制它的调用者时,后台工作程序将终止并且不会继续其剩余任务。
所以我会创建按钮处理程序 async
并在那里执行 http 请求:
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 线程上继续执行!所以你可以安全地更新进度条,因为你不是从另一个线程做的。
希望对您有所帮助。请注意,我将 pbCounter.Maximum
设置为您要 运行 的循环次数,因此您无需计算百分比。
我过去曾在 Windows 表单应用程序中使用过 BackgroundWorker
。
对于我的新练习,我需要在 worker 中使用 async
方法,对此我有点困惑。
这是我的代码结构。在表单加载事件中,我正在创建 BackgroundWorker
对象和设置事件
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 );
}
当用户点击一个按钮时,我将启动 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
处理程序 returns 控制它的调用者时,后台工作程序将终止并且不会继续其剩余任务。
所以我会创建按钮处理程序 async
并在那里执行 http 请求:
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 线程上继续执行!所以你可以安全地更新进度条,因为你不是从另一个线程做的。
希望对您有所帮助。请注意,我将 pbCounter.Maximum
设置为您要 运行 的循环次数,因此您无需计算百分比。