Omn*_*Owl 1 c# wpf asynchronous web-services
我已经尝试(并且失败)从WPF应用程序进行异步Web服务调用.
BackgroundWorker当我按下GUI上的"发送"按钮时,我在我的代码中实现了一个应该完成工作的代码.它在某些时候做了它应该做的事情,但最终它实际上并不是异步运行.
当您按下我的GUI中的按钮时,以下代码将触发:
private void btnSend_Click(object sender, RoutedEventArgs e)
{
sQuantity = boxQuantity.Text;
progressBar.Maximum = double.Parse(sQuantity);
worker.RunWorkerAsync();
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
最终,这是我搞砸的地方.我希望应用程序发送与用户指定的请求一样多的请求.所以,如果我写了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;
}
Run Code Online (Sandbox Code Playgroud)
我如何使该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;
}
Run Code Online (Sandbox Code Playgroud)
主下载将创建速率限制SemaphoreSlim(用于限制并发异步操作的常见类型),并等待所有单个下载完成:
private async Task DownloadAsync(int quantity)
{
var semaphore = new SemaphoreSlim(quantity);
var tasks = GetData().Select(dto => DownloadAsync(dto, semaphore));
await Task.WhenAll(tasks);
}
Run Code Online (Sandbox Code Playgroud)
个人下载将首先限制自己,然后进行实际下载:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
为了进行进度报告,我建议使用针对该模式的类型(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;
}
Run Code Online (Sandbox Code Playgroud)
(请注意,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);
}
Run Code Online (Sandbox Code Playgroud)
当您有进度报告时,您可以使用该实例:
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();
}
}
Run Code Online (Sandbox Code Playgroud)