我正在创建一个需要todo并行http请求的应用程序,我正在使用HttpClient。 我正在遍历网址和foreach URl我开始一个新的任务todo请求。 在循环之后,我等待直到每个任务完成。 但是,当我检查使用fiddler进行的调用时,我看到请求是同步调用的。它不像是一堆请求,而是一个接一个。 我搜索了一个解决方案,发现其他人也经历过这个,但不是UWP。解决方案是增加ServicePointManager上的DefaultConnectionLimit。 问题是UWP不存在ServicePointManager。我查看了API,我想我可以在HttpClientHandler上设置DefaultConnectionLimit,但是没有。
所以我有几个问题。 DefaultConnectionLimit仍然是可以在某处设置的属性吗? 如果是的话,我在哪里设置它? 如果没有,我该如何增加连接限制? UWP中是否还有连接限制?
这是我的代码:
var requests = new List<Task>();
var client = GetHttpClient();
foreach (var show in shows)
{
requests.Add(Task.Factory.StartNew((x) =>
{
((Show)x).NextEpisode = GetEpisodeAsync(((Show)x).NextEpisodeUri, client).Result;}, show));
}
}
await Task.WhenAll(requests.ToArray());
这是请求:
public async Task<Episode> GetEpisodeAsync(string nextEpisodeUri, HttpClient client)
{
try
{
if (String.IsNullOrWhiteSpace(nextEpisodeUri)) return null;
HttpResponseMessage content; = await client.GetAsync(nextEpisodeUri);
if (content.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<EpisodeWrapper>(await content.Content.ReadAsStringAsync()).Episode;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return null;
}
答案 0 :(得分:0)
欧客。我有解决方案。我确实需要在任务中使用async / await。问题是我使用StartNew而不是Run。但我必须使用StartNew,因为我正在通过一个州。 随着StartNew。除非您调用Unwrap,否则不会等待任务内部的任务。所以Task.StartNew(.....)。解包()。这样Task.WhenAll()将等待内部任务完成。 当你使用Task.Run()时,你不必这样做。
var requests = new List<Task>();
var client = GetHttpClient();
foreach (var show in shows)
{
requests.Add(Task.Factory.StartNew(async (x) =>
{
((Show)x).NextEpisode = await GetEpisodeAsync(((Show)x).NextEpisodeUri, client);
}, show)
.Unwrap());
}
Task.WaitAll(requests.ToArray());
答案 1 :(得分:0)
我认为解决此问题的简便方法不是“手动”启动请求,而是使用带有异步委托的linq来查询情节,然后再进行设置。
您基本上将其分为两个步骤:
这还具有将查询代码与设置节目的副作用脱钩的好处。
var shows = Enumerable.Range(0, 10).Select(x => new Show());
var client = new HttpClient();
(Show, Episode)[] nextEpisodes = await Task.WhenAll(shows
.Select(async show =>
(show, await GetEpisodeAsync(show.NextEpisodeUri, client))));
foreach ((Show Show, Episode Episode) tuple in nextEpisodes)
{
tuple.Show.NextEpisode = tuple.Episode;
}
请注意,我正在使用C#7的新元组语法。如果不可用,请相应地更改为旧的元组语法。