C# 使用aysnc并行调用webservice

C# 使用aysnc并行调用webservice,c#,winforms,asynchronous,soap-client,C#,Winforms,Asynchronous,Soap Client,我正在尝试编写一个winforms应用程序,它从SOAP web服务检索ID列表,然后遍历该列表,调用另一个web服务以获取个人详细信息。为了加快速度,我并行处理这些请求,一批15个 当web服务调用all return OK时,我的应用程序工作得很好。然而,在我的测试中,如果有2个或更多的请求超时(我正在使用Fiddler监视请求,并看到我得到了一个408),那么进程似乎会挂起,并且我从未得到我的程序应该显示的完成消息 如果可能的话,我想做的是重试这些请求,或者只是告诉用户再次按下按钮,因为发

我正在尝试编写一个winforms应用程序,它从SOAP web服务检索ID列表,然后遍历该列表,调用另一个web服务以获取个人详细信息。为了加快速度,我并行处理这些请求,一批15个

当web服务调用all return OK时,我的应用程序工作得很好。然而,在我的测试中,如果有2个或更多的请求超时(我正在使用Fiddler监视请求,并看到我得到了一个408),那么进程似乎会挂起,并且我从未得到我的程序应该显示的完成消息

如果可能的话,我想做的是重试这些请求,或者只是告诉用户再次按下按钮,因为发生了错误

添加服务引用时,我确保使用了generate task-based operations选项

以下是我迄今为止获得的代码(其中一些细节更名为“不泄露我与之接触的公司”):

private async void btnDownload\u单击(对象发送方,事件参数e)
{
尝试
{
秒表=新秒表();
watch.Start();
i进度=新进度(s=>
{
lbinfo.Items.Insert(0,s);
});
等待获取数据(进度);
看,停;
进度报告(“耗时”+(watch.elapsedmillyses/1000f)+“秒。全部完成”);
}
捕获(例外情况除外)
{
Show(“主点击:+ex.ToString());
}
}
专用异步任务GetData(IProgress进程)
{
尝试
{
DownloadSoapClient=new DownloadSoapClient();
client.Open();
进度报告(“获取主列表”);
List uniqueid=wait GetMasterList(client);//这似乎总是有效的
进度报告(“下载的主列表.找到”+uniqueIds.Count+“唯一ID”);
var detailedData=await GetIdDataRaw(uniqueid、client、progress);
client.Close();
}
捕获(例外情况除外)
{
进度报告(“GetData:+ex”);
}
}
专用异步任务GetIdDataRaw(列出ID、下载SoapClient客户端、IProgress进程)
{
使用(var节流器=新信号量LIM(15))
{
var allTasks=ids.Select(异步x=>
{
wait throttler.WaitAsync();
尝试
{
进度报告(x.ToString());
返回wait client.downloadsync(用户名、密码、x);
}
捕获(例外情况除外)
{
进度报告(“获取id时出错:+x+”+ex.Message);
返回null;
}
最后
{
节流器释放();
}
});
return(wait Task.WhenAll(allTasks)).ToList();
}
}
通常,主列表大约有1000个条目,当只有1次超时时,正如预期的那样,我会收到一条消息,说获取id xxxx时出错,然后“花了xx秒。全部完成。”


到目前为止,我已经尝试了一些其他的事情,比如为每个请求创建一个客户端,以及重构以使用Task.when(在while循环中),但是当两个或更多请求失败时,这些都会表现出相同的行为

任务返回的任务。Wheall
将在其所有任务完成后才能完成。无论出现什么错误,这都是正确的。你确定没有看到服务器出现问题吗?从Fiddler中的响应可以看出,我发出的所有请求都在完成,要么是200,要么是408。调用方法
客户端时默认超时是多少。DownloadAsync
?我想是60秒。至少我检查client.InnerChannel.OperationTimeout时是这样的。您能从日志和进度条中指定应用程序挂起的阶段吗?
 private async void btnDownload_Click(object sender, EventArgs e)
        {
            try
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();

                IProgress<string> progress = new Progress<string>(s =>
                {
                    lbinfo.Items.Insert(0, s);
                });

                await GetData(progress);

                watch.Stop();

                progress.Report("Took " + (watch.ElapsedMilliseconds / 1000f) + " seconds. All done.");
            }
            catch(Exception ex)
            {
                MessageBox.Show("Main Click: "+ex.ToString());
            }
        }

 private async Task GetData(IProgress<string> progress)
        {
            try
            {
                DownloadSoapClient client = new DownloadSoapClient();
                client.Open();

                progress.Report("Getting master list.");
                List<int> uniqueIds = await GetMasterList(client); //this always seems to work

                progress.Report("Downloaded master list. Found "+uniqueIds.Count +" unique ids.");

                var detailedData = await GetIdDataRaw(uniqueIds, client,progress);

                client.Close();

            }
            catch (Exception ex)
            {
                progress.Report("GetData: "+ex);
            }
        }

       private async Task<List<DownloadResponse>> GetIdDataRaw(List<int> ids, DownloadSoapClient client, IProgress<string> progress)
        {
            using (var throttler = new SemaphoreSlim(15))
            {
                var allTasks = ids.Select(async x =>
                    {
                        await throttler.WaitAsync();

                        try
                        {
                            progress.Report(x.ToString());
                            return await client.DownloadAsync(username, password, x);

                        }
                        catch (Exception ex)
                        {
                            progress.Report("Error getting id:" + x + " " + ex.Message);
                            return null;
                        }
                        finally
                        {
                            throttler.Release();
                        }
                    });

                return (await Task.WhenAll(allTasks)).ToList();
            }
        }