从 backgroundworker 迁移到 async / await 方法

Posted

技术标签:

【中文标题】从 backgroundworker 迁移到 async / await 方法【英文标题】:Migrate from backgroundworker to async / await methods 【发布时间】:2013-08-17 15:44:24 【问题描述】:

我一直在 WinForms C# 应用程序 BackgroundWorkers 中使用如下所示的任何 WCF 服务数据调用:

private void Worker_DoWork(object sender, DoWorkEventArgs e)
        
            switch (_workerType)
            
                case "search":


                    Data.SeekWCF seekWcf = new Data.SeekWCF();
                    _ds = seekWcf.SearchInvoiceAdmin(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value));
                    seekWcf.Dispose();

                    break;

                case "update":

                    Data.AccountingWCF accWcf = new Data.AccountingWCF();
                    _returnVal = accWcf.UpdateInvoiceAdmin(_ds);
                    accWcf.Dispose();

                    break;
            
        

例如,为了调用后台工作人员:

private void btnSearch_Click(object sender, EventArgs e)
        
            if (!_worker.IsBusy)
                

                    ShowPleaseWait(Translate("Searching data. Please wait..."));
                    _workerType = "search";
                    _worker.RunWorkerAsync();
                
        

现在,我想开始迁移到 Task (async / await) C# 5.0,所以我在这个示例中所做的是:

private async void ProcessSearch()
        

            Data.SeekWCF seekWcf = new Data.SeekWCF();
            _ds = seekWcf.SearchInvoiceAdmin(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value));
            seekWcf.Dispose();
        

但是在这里我收到一条消息说“这个异步方法缺少'await'运算符并且将同步运行”。

任何关于最佳实践和正确方法来完成我想要完成的事情的线索?

【问题讨论】:

【参考方案1】:

理想情况下,您的 WCF 服务包装器应具有其方法的异步版本,即 SearchInvoiceAdminAsync。然后你会等待它:

        private async Task ProcessSearchAsync()
        

            Data.SeekWCF seekWcf = new Data.SeekWCF();
            _ds = await seekWcf.SearchInvoiceAdminAsync(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value));
            seekWcf.Dispose();
        

已编辑:不同的是,最终您需要从常规方法调用异步方法,例如,在单击按钮时,并且可能在任务完成时执行某些操作。这是一个非常简单的场景:

// UI Thread

Task _pendingTask = null;

void button_click()

    if ( _pendingTask != null)
    
        MessageBox.Show("Still working!");
    
    else
    
        _pendingTask = ProcessSearchAsync();


        _pendingTask.ContinueWith((t) =>
        
            MessageBox.Show("Task is done!");
            // check _pendingTask.IsFaulted here
            _pendingTask = null;
        , TaskScheduler.FromCurrentSynchronizationContext());
    

已编辑:注意,最初我在调用ContinueWith 时忘记指定TaskScheduler。这可能会导致在池线程上调用 continuationAction

【讨论】:

如何将我的 WCF 方法转换为异步方法? 只需为其重新生成 C# 包装器,这里是 how。 我所做的是右键单击服务和“配置服务引用...”,然后我检查选项“允许生成异步操作”.. 并再次编译它,我没有看到添加了任何异步方法..任何线索=? 在“允许生成异步操作”下面还有两个单选按钮,“生成基于任务的操作”和“生成异步操作”。选择后者。 更正:“生成基于任务的操作”(第一个选项)。但那是你默认的,对吧?也许您应该删除引用并重新添加它。

以上是关于从 backgroundworker 迁移到 async / await 方法的主要内容,如果未能解决你的问题,请参考以下文章

将应用程序从AS2迁移到AS3有哪些优缺点?

从 JBoss AS 7.1 迁移到 JBoss EAP 7.3.0

是不是 .NET 4.0 TPL 让 APM、EAP 和 BackgroundWorker 异步模式过时了?

EJB 远程客户端从 JBoss AS 7.1 迁移到 Wildfly 8.1

EJB远程客户端从JBoss AS 7.1迁移到Wildfly 8.1

JBoss as7 到 WildFly 的 Hibernate 迁移