C#,最大化线程并发
C#, Maximize Thread Concurrency
在 Google 和社区的帮助下,我能够构建一组不错的方法,允许我异步调用函数。该函数正在测试远程主机属性,因此大部分时间处于空闲状态。出于这个原因,我想最大化启动的并发线程数,以便可以在最短的时间内处理所有调用。
这是我目前的代码:
// Check remote host connectivity
public static class CheckRemoteHost
{
// Private Class members
private static bool AllDone = false;
private static object lockObj = new object();
private static List<string> IPs;
// Wrapper: manage async method <Ping>
public static List<string> Ping(HashSet<string> IP_Ports, int TimeoutInMS = 100)
{// async worker method: check remote host via <Ping>
// Locals
IPs = new List<string>();
// Perform remote host check
AllDone = false;
Ping_check(IP_Ports, TimeoutInMS);
while (!AllDone) { CommonLib.Utils.ApplicationWait(10, 10); }
// Finish
return IPs;
}
private static async void Ping_check(HashSet<string> IP_Ports, int timeout)
{
// Locals
var tasks = new List<Task>();
// Build task-set for parallel Ping checks
foreach (string host in IP_Ports)
{
var task = PingAndUpdateAsync(host, timeout);
tasks.Add(task);
}
// Start execution queue
await Task.WhenAll(tasks).ContinueWith(t =>
{
AllDone = true;
});
}
private static async Task PingAndUpdateAsync(string ip, int timeout)
{
// Locals
System.Net.NetworkInformation.Ping ping;
System.Net.NetworkInformation.PingReply reply;
try
{
ping = new System.Net.NetworkInformation.Ping();
reply = await ping.SendPingAsync(ip, timeout);
if(reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
lock (lockObj)
{
IPs.Add(ip);
}
}
}
catch
{
// do nothing
}
}
}// end public static class CheckRemoteHost
此代码经过了相当广泛的测试,代码看起来稳定且可靠地报告实时主机。话虽如此,我知道它一次只产生 8 个线程(= 我测试机器上的逻辑核心数)。
代码的关键部分是这样的:
// Start execution queue
await Task.WhenAll(tasks).ContinueWith(t =>
{
AllDone = true;
});
这是我想将同时启动的线程数增加/最大化到大约每个内核 25 个(记住线程作业有 99% 空闲)的地方。
到目前为止,我的线程并发研究提出了显式线程和 Parallel.For 方法。然而,这些似乎有相同的缺点,即生成不超过 8 个线程。
非常感谢任何帮助,因此非常感谢大家的关注!
你的代码让你的生活变得艰难。它有很多不需要的管道,并且您正在共享静态字段,如果您第二次调用 Ping
而第一个是 运行.[=13 ,这将导致您的代码失败=]
你需要摆脱所有这些东西。
我建议使用 Microsoft 的 Reactive Framework - 只需 NuGet "System.Reactive" 并将 using System.Reactive.Linq;
添加到您的代码中。那么你可以这样做:
public static class CheckRemoteHost
{
public static IList<string> Ping(HashSet<string> IP_Ports, int TimeoutInMS = 100)
{
var query =
from host in IP_Ports.ToObservable()
from status in Observable.FromAsync(() => PingAsync(host, TimeoutInMS))
where status
select host;
return query.ToList().Wait();
}
private static async Task<bool> PingAsync(string ip, int timeout)
{
try
{
var ping = new System.Net.NetworkInformation.Ping();
var reply = await ping.SendPingAsync(ip, timeout);
return reply.Status == System.Net.NetworkInformation.IPStatus.Success;
}
catch
{
return false;
}
}
}
就是这样。这就是您需要的所有代码。它会自动最大化线程使用来完成工作。
在 Google 和社区的帮助下,我能够构建一组不错的方法,允许我异步调用函数。该函数正在测试远程主机属性,因此大部分时间处于空闲状态。出于这个原因,我想最大化启动的并发线程数,以便可以在最短的时间内处理所有调用。
这是我目前的代码:
// Check remote host connectivity
public static class CheckRemoteHost
{
// Private Class members
private static bool AllDone = false;
private static object lockObj = new object();
private static List<string> IPs;
// Wrapper: manage async method <Ping>
public static List<string> Ping(HashSet<string> IP_Ports, int TimeoutInMS = 100)
{// async worker method: check remote host via <Ping>
// Locals
IPs = new List<string>();
// Perform remote host check
AllDone = false;
Ping_check(IP_Ports, TimeoutInMS);
while (!AllDone) { CommonLib.Utils.ApplicationWait(10, 10); }
// Finish
return IPs;
}
private static async void Ping_check(HashSet<string> IP_Ports, int timeout)
{
// Locals
var tasks = new List<Task>();
// Build task-set for parallel Ping checks
foreach (string host in IP_Ports)
{
var task = PingAndUpdateAsync(host, timeout);
tasks.Add(task);
}
// Start execution queue
await Task.WhenAll(tasks).ContinueWith(t =>
{
AllDone = true;
});
}
private static async Task PingAndUpdateAsync(string ip, int timeout)
{
// Locals
System.Net.NetworkInformation.Ping ping;
System.Net.NetworkInformation.PingReply reply;
try
{
ping = new System.Net.NetworkInformation.Ping();
reply = await ping.SendPingAsync(ip, timeout);
if(reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
lock (lockObj)
{
IPs.Add(ip);
}
}
}
catch
{
// do nothing
}
}
}// end public static class CheckRemoteHost
此代码经过了相当广泛的测试,代码看起来稳定且可靠地报告实时主机。话虽如此,我知道它一次只产生 8 个线程(= 我测试机器上的逻辑核心数)。
代码的关键部分是这样的:
// Start execution queue
await Task.WhenAll(tasks).ContinueWith(t =>
{
AllDone = true;
});
这是我想将同时启动的线程数增加/最大化到大约每个内核 25 个(记住线程作业有 99% 空闲)的地方。
到目前为止,我的线程并发研究提出了显式线程和 Parallel.For 方法。然而,这些似乎有相同的缺点,即生成不超过 8 个线程。
非常感谢任何帮助,因此非常感谢大家的关注!
你的代码让你的生活变得艰难。它有很多不需要的管道,并且您正在共享静态字段,如果您第二次调用 Ping
而第一个是 运行.[=13 ,这将导致您的代码失败=]
你需要摆脱所有这些东西。
我建议使用 Microsoft 的 Reactive Framework - 只需 NuGet "System.Reactive" 并将 using System.Reactive.Linq;
添加到您的代码中。那么你可以这样做:
public static class CheckRemoteHost
{
public static IList<string> Ping(HashSet<string> IP_Ports, int TimeoutInMS = 100)
{
var query =
from host in IP_Ports.ToObservable()
from status in Observable.FromAsync(() => PingAsync(host, TimeoutInMS))
where status
select host;
return query.ToList().Wait();
}
private static async Task<bool> PingAsync(string ip, int timeout)
{
try
{
var ping = new System.Net.NetworkInformation.Ping();
var reply = await ping.SendPingAsync(ip, timeout);
return reply.Status == System.Net.NetworkInformation.IPStatus.Success;
}
catch
{
return false;
}
}
}
就是这样。这就是您需要的所有代码。它会自动最大化线程使用来完成工作。