【发布时间】:2018-06-28 20:26:48
【问题描述】:
在 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 个线程。
任何帮助将不胜感激,因此非常感谢大家的关注!
【问题讨论】:
-
类似this ?
-
任务!=线程。您可以在单个线程上运行数千个任务。使用异步工作流程,您不希望线程数多于内核数 - 您希望线程数尽可能少。
-
@CoryNelson
You don't want more threads than you have cores陈词滥调。如果我的所有线程都被一些 IO(磁盘,NW)阻塞,为什么我不会在所有内核都空闲时创建一个新线程。 -
@Eser 正如我所说,用于异步工作流。异步中不应有任何阻塞 I/O。
-
@supersausage007 在发送新的 ping 之前,您不必等待上一个 ping 的回答。这就是为什么在链接的示例中,有一个线程专门用于发送它们,一个线程专门用于读取回复。
标签: c# multithreading concurrency task maximize