访问 foreach 中 LINQ Select 中使用的值
Accessing value used in LINQ Select within a foreach
给定 IP 地址列表:
List<string> ipList = new List<string>(); //example: 192.168.0.1, 192.168.0.2, 192.168.0.3 etc.
我试图以并行方式遍历列表中的每个 IP,然后在屏幕上打印一条有意义的消息:
foreach (PingReply pingReply in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => new Ping().Send(ip)))
{
Console.WriteLine($"Ping status: {pingReply.Status} for the target IP address: {ip}");
}
我无法在该上下文中访问 ip
。我真的很想了解如何访问每个 relative ip
当我发送它们时?
我已经探索了 PingReply
object but PingReply.Address
作为示例包含主机(发件人)IP,因此它无法满足此要求。我真的希望 PingReply
对象包含被 ping 的 Ip!
更新
根据@haim770 和@MindSwipe 提供的示例,我最终使用了:
foreach (var pingResponseData in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => new { ip, pingReply = new Ping().Send(ip) }))
{
Console.WriteLine($"Ping status: {pingResponseData.pingReply.Status} for the target IP address: {pingResponseData.ip}");
}
更新 2
根据@pinkfloydx33 关于使用 ValueTuple
的评论,我已按照以下示例完成:
foreach (var (ip, reply) in ipList.AsParallel().WithDegreeOfParallelism(ipList.Count).Select(ip => (ip, new Ping().Send(ip, 150))))
{
Console.WriteLine($"Ping status: {reply.Status} for the target IP address: {ip}");
}
您目前只selectpingReply
,而不是ip
和pingReply
,为此您需要select 一个新的 anonymous type 并对其进行迭代。像这样:
foreach (var (pingReply, ip) in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => (ip, Ping().Send(ip))))
{
// Here 'i' is an object with the properties 'ip' and 'pingReply'
Console.WriteLine($"Ping status: {i.pingReply.Status} for the target IP address: {i.ip}");
}
编辑: 现在才注意到 haim770 posted basically this in
编辑 2: 谢谢 pinkfloydx33 for pointing out I could use tuple deconsturcting
并行度=64并行调用同步Ping.Send
效率很低,因为并行执行时阻塞了多达64个线程(前提是ThreadPool
有足够的线程能否满足需求,这是值得怀疑的)。例如,执行 ping 的更有效方法是使用异步 Ping.SendPingAsync
method. To invoke this method in a way that no more than 64 asynchronous operations will be simultaneously in-flight, you will need a Parallel.ForEach
equivalent that works with asynchronous delegates. Currently there is no such thing available built-in (it will probably be available in .NET 6), but you can find lots of custom implementations if you search for ForEachAsync
. There is one here。然后你就可以这样做了:
var ipList = new List<string>() {"192.168.0.1", "192.168.0.2", "192.168.0.3"}; // etc
ipList.ForEachAsync(async ip =>
{
var ping = new Ping();
var reply = await ping.SendPingAsync(ip);
Console.WriteLine($"IP '{ip}' ping reply status: {reply.Status}");
}, dop: 64).Wait();
您也可以 await
完成操作,而不是使用阻塞 Wait
,前提是您从 async
方法调用它。
给定 IP 地址列表:
List<string> ipList = new List<string>(); //example: 192.168.0.1, 192.168.0.2, 192.168.0.3 etc.
我试图以并行方式遍历列表中的每个 IP,然后在屏幕上打印一条有意义的消息:
foreach (PingReply pingReply in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => new Ping().Send(ip)))
{
Console.WriteLine($"Ping status: {pingReply.Status} for the target IP address: {ip}");
}
我无法在该上下文中访问 ip
。我真的很想了解如何访问每个 relative ip
当我发送它们时?
我已经探索了 PingReply
object but PingReply.Address
作为示例包含主机(发件人)IP,因此它无法满足此要求。我真的希望 PingReply
对象包含被 ping 的 Ip!
更新
根据@haim770 和@MindSwipe 提供的示例,我最终使用了:
foreach (var pingResponseData in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => new { ip, pingReply = new Ping().Send(ip) }))
{
Console.WriteLine($"Ping status: {pingResponseData.pingReply.Status} for the target IP address: {pingResponseData.ip}");
}
更新 2
根据@pinkfloydx33 关于使用 ValueTuple
的评论,我已按照以下示例完成:
foreach (var (ip, reply) in ipList.AsParallel().WithDegreeOfParallelism(ipList.Count).Select(ip => (ip, new Ping().Send(ip, 150))))
{
Console.WriteLine($"Ping status: {reply.Status} for the target IP address: {ip}");
}
您目前只selectpingReply
,而不是ip
和pingReply
,为此您需要select 一个新的 anonymous type 并对其进行迭代。像这样:
foreach (var (pingReply, ip) in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => (ip, Ping().Send(ip))))
{
// Here 'i' is an object with the properties 'ip' and 'pingReply'
Console.WriteLine($"Ping status: {i.pingReply.Status} for the target IP address: {i.ip}");
}
编辑: 现在才注意到 haim770 posted basically this in
编辑 2: 谢谢 pinkfloydx33 for pointing out I could use tuple deconsturcting
并行度=64并行调用同步Ping.Send
效率很低,因为并行执行时阻塞了多达64个线程(前提是ThreadPool
有足够的线程能否满足需求,这是值得怀疑的)。例如,执行 ping 的更有效方法是使用异步 Ping.SendPingAsync
method. To invoke this method in a way that no more than 64 asynchronous operations will be simultaneously in-flight, you will need a Parallel.ForEach
equivalent that works with asynchronous delegates. Currently there is no such thing available built-in (it will probably be available in .NET 6), but you can find lots of custom implementations if you search for ForEachAsync
. There is one here。然后你就可以这样做了:
var ipList = new List<string>() {"192.168.0.1", "192.168.0.2", "192.168.0.3"}; // etc
ipList.ForEachAsync(async ip =>
{
var ping = new Ping();
var reply = await ping.SendPingAsync(ip);
Console.WriteLine($"IP '{ip}' ping reply status: {reply.Status}");
}, dop: 64).Wait();
您也可以 await
完成操作,而不是使用阻塞 Wait
,前提是您从 async
方法调用它。