来自WPF的异步Web服务请求

猫头鹰

我尝试过(但失败了)从WPF应用程序进行异步Web服务调用。

BackgroundWorker当您按我的GUI上的“发送”按钮时,我在我的代码中实现了应该执行的工作。有时会执行预期的操作,但最终实际上并没有异步运行。

当您在我的GUI中按下按钮时,将触发以下代码:

private void btnSend_Click(object sender, RoutedEventArgs e)
{
    sQuantity = boxQuantity.Text;
    progressBar.Maximum = double.Parse(sQuantity);
    worker.RunWorkerAsync();
}

sQuantity只是一个有数字的盒子。它将确定您一次发送到Web服务的请求数量。

progressBar 是您期望的:进度条。

worker.RunWorkerAsync()是我调用该DoWork方法的地方。看起来像这样:

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    EnableButton(false);
    List<LoanRequestNoCreditScoreDTO> dtoList = GetData();
    foreach (LoanRequestNoCreditScoreDTO dto in dtoList)
    {
        using (LoanBrokerWS.LoanBrokerWSClient client = new LoanBrokerWS.LoanBrokerWSClient())
        {
            try
            {
                Task<LoanQuoteDTO> lq = RequestQuote(dto, client);
                LoanQuoteDTO response = lq.Result;
                lq.Dispose();
                String responseMsg = response.SSN + "\n" + response.interestRate + "\n" + response.BankName + "\n------\n";
                AppendText(responseMsg);
                worker_ProgressChanged();
            }
            catch (Exception ex)
            {
                AppendText(ex.Message + "\n" + ex.InnerException.Message + "\n");
                worker_ProgressChanged();
            }
        }
    }
    EnableButton(true);
}

最终,这是我理所当然的地方。我希望应用程序发送与用户指定数量一样多的请求。因此,如果我写了10封,我将发送10封请求。RequestQuote()方法调用以下代码:

private async Task<LoanQuoteDTO> RequestQuote(LoanRequestNoCreditScoreDTO dto, LoanBrokerWS.LoanBrokerWSClient client)
{
    LoanQuoteDTO response = await client.GetLoanQuoteAsync(dto.SSN, dto.LoanAmount, dto.LoanDuration);
    return response;
}

我将如何使该DoWork方法实际发送请求异步?

斯蒂芬·克莱里

就UI线程而言,代码原样是异步的;您在问它的并发性是什么任何类型的复杂I / O工作都最好使用async/来完成await,因此我将淘汰您的后台工作人员,而直接使用async

首先,按钮处理程序将处理其自己的启用/禁用和执行主要下载:

private async void btnSend_Click(object sender, RoutedEventArgs e)
{
  var quantity = int.Parse(boxQuantity.Text);
  btnSend.Enabled = false;
  await DownloadAsync(quantity);
  btnSend.Enabled = true;
}

主要下载将创建一个速率限制SemaphoreSlim(一种用于限制并发异步操作的通用类型),并等待所有单个下载完成:

private async Task DownloadAsync(int quantity)
{
  var semaphore = new SemaphoreSlim(quantity);
  var tasks = GetData().Select(dto => DownloadAsync(dto, semaphore));
  await Task.WhenAll(tasks);
}

单独的下载将各自先限制自己的速率,然后再进行实际的下载:

private async Task DownloadAsync(LoanRequestNoCreditScoreDTO dto, SemaphoreSlim semaphore)
{
  await semaphore.WaitAsync();
  try
  {
    using (LoanBrokerWS.LoanBrokerWSClient client = new LoanBrokerWS.LoanBrokerWSClient())
    {
      var response = await RequestQuoteAsync(dto, client);
    }        
  }
  finally
  {
    semaphore.Release();
  }
}

对于进度报告,我建议使用用于该模式的类型(IProgress<T>/ Progress<T>)。首先,您决定要在进度报告中使用哪些数据;在这种情况下,它可能只是一个字符串。然后,您创建进度处理程序:

private async void btnSend_Click(object sender, RoutedEventArgs e)
{
  var quantity = int.Parse(boxQuantity.Text);
  var progress = new Progress<string>(update =>
  {
    AppendText(update);
    progressBar.Value = progressBar.Value + 1;
  });
  progressBar.Maximum = ...; // not "quantity"
  btnSend.Enabled = false;
  await DownloadAsync(quantity, progress);
  btnSend.Enabled = true;
}

(请注意,progressBar.Maximum = double.Parse(sQuantity);原始代码中的错误;您应该将其设置为下载总数)。

然后IProgress<string>公正传下来:

private async Task DownloadAsync(int quantity, IProgress<string> progress)
{
  var semaphore = new SemaphoreSlim(quantity);
  var tasks = GetData().Select(dto => DownloadAsync(dto, semaphore, progress));
  await Task.WhenAll(tasks);
}

而且,当您有进度报告时,可以使用该实例:

private async Task DownloadAsync(LoanRequestNoCreditScoreDTO dto, SemaphoreSlim semaphore, IProgress<string> progress)
{
  await semaphore.WaitAsync();
  try
  {
    using (LoanBrokerWS.LoanBrokerWSClient client = new LoanBrokerWS.LoanBrokerWSClient())
    {
      var response = await RequestQuoteAsync(dto, client);
      progress.Report(response.SSN + "\n" + response.interestRate + "\n" + response.BankName + "\n------\n");
    }
  }
  catch (Exception ex)
  {
    progress.Report(ex.Message + "\n" + ex.InnerException.Message + "\n");
  }
  finally
  {
    semaphore.Release();
  }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

调试Web服务请求

Ajax Web服务请求

来自html中单个页面的多个Web服务请求

Windows Phone模拟器未显示来自跨域Web服务请求的安全警告

VBScript / CATScript Web服务请求Unix

Web服务请求中的While语句

显示Javascript Ajax Web服务请求

Soap Web服务请求与HTTP POST请求?

当minOccurs = 1时,来自SoapUI的Web服务请求(缺少int参数)会自动分配0值

Web服务请求执行时间计算

运行Web服务请求的线程池的合理线程数

Java Web服务请求参数返回为null

如何从 dataTaskWithRequest 打印 Web 服务请求和响应

WCF Web服务请求的数据协定序列化

如何使用AFNetworking或STHTTPRequest发出SOAP Web服务请求?

ColdFusion 最大同时 Web 服务请求数

记录和重播RealityServer Web服务请求

JSON代理:尽可能无处不在地执行来自单页HTML应用程序的跨域Web服务请求吗?

重定向/转发SOAP Web服务请求到另一个Web服务

如何使用Qaf Web服务请求调用管理具有多个请求的cookie?

可以将ajax发送的每个请求(xmlhttprequest)称为Web服务请求吗?

来自Web服务的异步响应-CXF JAXWS

使用可选选项重写服务请求

最小化服务请求

如何向服务请求权限

将累加器逻辑添加到Web服务请求时出现XSLT错误

如何为自动生成的SOAP Web服务请求提供相同的接口?

HTTPS POST Web服务请求格式-在子节点内插入多个值

在junit中模拟亚马逊Web服务请求/响应对象