gpt4 book ai didi

c# - 基于网络的任务的多线程/并发策略

转载 作者:太空宇宙 更新时间:2023-11-03 20:56:49 24 4
gpt4 key购买 nike

我不擅长充分利用资源,因此我正在寻找最好的方法来完成一项需要并行且高效地完成的任务。

我们有一个场景,我们必须 ping 数百万个系统并收到响应。响应本身不需要计算时间,但任务是基于网络的。

我目前的实现是这样的——

Parallel.ForEach(list, ip =>
{
try
{
// var record = client.QueryAsync(ip);
var record = client.Query(ip);
results.Add(record);
}
catch (Exception)
{
failed.Add(ip);
}
});

我测试了这段代码

  • 100 项大约需要 4 秒
  • 1k 项大约需要 10 秒
  • 10k 项大约需要 80 秒
  • 10 万个项目大约需要 710 秒

我需要处理近 2000 万个查询,我应该使用什么策略来进一步加快速度

最佳答案

问题来了

Parallel.ForEach 使用线程池。此外,IO 绑定(bind) 操作将阻塞那些等待设备响应并占用资源的线程。

  • 如果您有 CPU bound 代码,Parallelism 是合适的;
  • 虽然如果您有IO 绑定(bind) 代码,异步 是合适的。

在这种情况下,client.Query 显然是I/O,因此理想的消费代码应该是异步的。

既然你说有一个异步版本,你最好使用 async/await 模式和/或某种类型的并发任务限制,另一个巧妙的解决方案是使用 ActionBlock ClassTPL dataflow图书馆。


数据流示例

public static async Task DoWorkLoads(List<IPAddress> addresses)
{
var options = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 50
};

var block = new ActionBlock<IPAddress>(MyMethodAsync, options);

foreach (var ip in addresses)
block.Post(ip);

block.Complete();
await block.Completion;

}

...

public async Task MyMethodAsync(IpAddress ip)
{

try
{
var record = await client.Query(ip);
// note this is not thread safe best to lock it
results.Add(record);
}
catch (Exception)
{
// note this is not thread safe best to lock it
failed.Add(ip);
}
}

这种方法给你异步,它也给你MaxDegreeOfParallelism,它不浪费资源,让IO成为 IO 无需消耗不必要的资源

*Disclaimer, DataFlow may not be where you want to be, however i just thought id give you some more information


Demo here

更新

我刚刚用 Parallel.Foreaceh 和 DataFlow 做了一些基准测试

多次运行10000 ping

Parallel.Foreach = 30 秒

数据流 = 10 秒

关于c# - 基于网络的任务的多线程/并发策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49669866/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com