我正在尝试处理每个请求,因为它完成了,ContinueWith
之后GetStringAsync
会发生什么,然后当它们全部完成时会有额外的处理。
但是,似乎ContinueWith
上的WhenAll
会立即触发。似乎GetStringAsync
任务是错误的,但我无法弄清楚原因。
当我使用WaitAll
代替WhenAll
并在WaitAll
之后添加我的处理时,我的请求工作正常。但当我将其更改为WhenAll
时,它会失败。
以下是我的代码示例:
using (var client = new HttpClient())
{
Task.WhenAll(services.Select(x =>
{
return client.GetStringAsync(x.Url).ContinueWith(response =>
{
Console.WriteLine(response.Result);
}, TaskContinuationOptions.AttachedToParent);
}).ToArray())
.ContinueWith(response =>
{
Console.WriteLine("All tasks completed");
});
}
答案 0 :(得分:2)
使用ContinueWith
时,不应使用TaskContinuationOptions.AttachedToParent
和async-await
。请仅使用async-await
:
async Task<IEnumerable<string>> SomeMethod(...)
{
using (var client = new HttpClient())
{
var ss = await Task.WhenAll(services.Select(async x =>
{
var s = await client.GetStringAsync(x.Url);
Console.WriteLine(response);
return s;
};
Console.WriteLine("All tasks completed");
return ss;
}
}
答案 1 :(得分:1)
好吧,我发现了这个问题。我会留在这里以防其他人出现寻找类似的答案。我仍然需要await
Task.WhenAll
方法。
所以,正确的代码是:
using (var client = new HttpClient())
{
await Task.WhenAll(services.Select(x =>
{
return client.GetStringAsync(x.Url).ContinueWith(response =>
{
Console.WriteLine(response.Result);
}, TaskContinuationOptions.AttachedToParent);
}).ToArray())
.ContinueWith(response =>
{
Console.WriteLine("All tasks completed");
});
}
答案 2 :(得分:0)
我仍然看到您的解决方案存在两个问题:
删除使用声明 - you don't want to dispose HttpClient。
删除ContinueWith
- 如果您正确使用await
,则不需要它们。
this MSDN article中描述的Task.WhenAny
方法在完成任务时处理的方式更为清晰。
我会像这样重写你的例子:
var client = new HttpClient();
var tasks = services.Select(x => client.GetStringAsync(x.Url)).ToList();
while (tasks.Count > 0)
{
var firstDone = await Task.WhenAny(tasks);
tasks.Remove(firstDone);
Console.WriteLine(await firstDone);
}
Console.WriteLine("All tasks completed");
如果您在完成任务时需要访问service
对象,则可以通过一种方法将tasks
修改为Task<ObjectWithMoreData>
而非Task<string>
的列表。请注意,lambda标记为async
,因此我们可以在其中await
:
var client = new HttpClient();
var tasks = services.Select(async x => new
{
Service = x,
ResponseText = await client.GetStringAsync(x.Url)
}).ToList();
while (tasks.Count > 0)
{
var firstDone = await Task.WhenAny(tasks);
tasks.Remove(firstDone);
var result = await firstDone;
Console.WriteLine(result.ResponseText);
// do something with result.Service
}
Console.WriteLine("All tasks completed");