Sup*_*Bob 4 c# concurrency asynchronous async-await parallel.foreach
我已阅读以下密切相关的主题,但我想问一个更具体的事情。
如果我们需要异步运行任务/方法,并且这些任务本身运行其他任务/等待其他任务,则首选哪种变体 - Parallel.ForEach,或Task.WhenAll?我将用下面的一些代码进行演示:
public async Task SomeWorker(string param1, HttpClient client,
List<FillMeUp> emptyCollection)
{
HttpRequestMessage message = new HttpRequestMessage();
message.Method = HttpMethod.Get;
message.Headers.Add("someParam", param1);
message.RequestUri = new Uri("https://www.somesite.me");
var requestResponse = await client.SendAsync(message).ConfigureAwait(false);
var content = await requestResponse.Content.ReadAsStringAsync()
.ConfigureAwait(false);
emptyCollection.Add(new FillMeUp()
{
Param1 = param1
});
}
Run Code Online (Sandbox Code Playgroud)
与 一起使用WhenAll:
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Accept", "application/json");
List<FullCollection> fullCollection = GetMyFullCollection();
List<FillMeUp> emptyCollection = new List<FillMeUp>();
List<Task> workers = new List<Task>();
for (int i = 0; i < fullCollection.Count; i++)
{
workers.Add(SomeWorker(fullCollection[i].SomeParam, client,
emptyCollection));
}
await Task.WhenAll(workers).ConfigureAwait(false);
// Do something below with already completed tasks
}
Run Code Online (Sandbox Code Playgroud)
或者,将以上所有内容写在Parallel.ForEach():
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Accept", "application/json");
List<FullCollection> fullCollection = GetMyFullCollection();
List<FillMeUp> emptyCollection = new List<FillMeUp>();
Parallel.ForEach<FullCollection>(fullCollection, (fullObject) =>
{
HttpRequestMessage message = new HttpRequestMessage();
message.Method = HttpMethod.Get;
message.Headers.Add("someParam", fullObject.SomeParam);
message.RequestUri = new Uri("https://www.somesite.me");
var requestResponse = client.SendAsync(message)
.GetAwaiter().GetResult();
var content = requestResponse.Content.ReadAsStringAsync()
.GetAwaiter().GetResult();
emptyCollection.Add(new FillMeUp()
{
Param1 = fullObject.SomeParam
});
});
}
Run Code Online (Sandbox Code Playgroud)
我知道列表不是线程安全的。这只是为了证明我的问题的性质。
HttpClient(SendAsync和)的两个方法ReadAsStringAsync都是异步的,因此必须同步调用才能使用Parallel.ForEach。
这比Task.WhenAll路线更受欢迎吗?我尝试了各种性能测试,但似乎找不到差异。
一般来说,Parallel当您的 CPU 有大量工作要做时,您就需要该类。Task当您必须等待外部世界为您完成大量工作时,您就需要该课程。
从.NET 6开始,Parallel现在配备了异步ForEachAsync方法,它接受异步body委托,并支持与同步方法相同的选项Parallel。最重要的选项是MaxDegreeOfParallelism,因为当请求溢出时,Web 服务器、文件系统和数据库都会表现得很糟糕。在此之前,我们必须求助于TPL Dataflow库等高级工具,或者编写自定义ForEachAsync实现,如本问题所示。
应该注意的是,Tasks 也可用于 CPU 密集型工作。该类在内部Parallel使用Tasks 作为构建块。这种关系通过总称任务并行库(TPL) 可以明显看出。
| 归档时间: |
|
| 查看次数: |
5154 次 |
| 最近记录: |