使用 HttpClient 异步方法的BackgroundWorker

问题描述 投票:0回答:2

我过去曾在 Windows 窗体应用程序中使用过

BackgroundWorker
。 对于我的新练习,我需要在工作人员内部使用
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 );
}

当用户单击按钮时,我正在启动工作程序

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 );
    }
}
c# async-await backgroundworker asp.net-4.5
2个回答
3
投票

如果您使用

async
await
,则不需要后台工作人员。事实上,您的后台工作人员将无法工作,因为当您使用
await
时,控制权会交还给调用者。当
DoWork
处理程序将控制权返回给其调用者时,后台工作人员将终止并且不再继续其剩余任务。

所以我会创建按钮处理程序

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
设置为您要运行的循环数,因此您不需要计算百分比。


0
投票

我看到 async void 答案被标记为最佳。但是如果等待的操作失败怎么办?

https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

参见提供的链接中的图 2。我很好奇,我在这里错过了什么?

© www.soinside.com 2019 - 2024. All rights reserved.