C# C、 最大化线程并发性
在Google和community的帮助下,我能够构建一组很好的方法,允许我异步调用函数。此函数正在测试远程主机属性,因此大部分时间处于空闲状态。出于这个原因,我希望最大化启动的并发线程的数量,这样所有调用都可以在最短的时间内处理 以下是我目前掌握的代码:C# C、 最大化线程并发性,c#,multithreading,concurrency,task,maximize,C#,Multithreading,Concurrency,Task,Maximize,在Google和community的帮助下,我能够构建一组很好的方法,允许我异步调用函数。此函数正在测试远程主机属性,因此大部分时间处于空闲状态。出于这个原因,我希望最大化启动的并发线程的数量,这样所有调用都可以在最短的时间内处理 以下是我目前掌握的代码: // Check remote host connectivity public static class CheckRemoteHost { // Private Class members private static
// 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
这就是我想增加/最大化并发启动线程的数量,使之达到每个核心25个线程的数量记住线程作业是99%空闲的
到目前为止,我的线程并发研究已经提出了显式线程和并行方法。但是,它们似乎有相同的缺点,即生成的线程不超过8个
任何帮助都将非常感谢,所以提前非常感谢大家的关注 你的代码让你的生活变得艰难。它有很多不需要的管道,并且共享静态字段,如果在第一次运行Ping时再次调用Ping,则会导致代码失败 你需要把那些东西都扔掉 我建议使用微软的反应式框架——只需使用System.Responsive和add-using System.Responsive.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;
}
}
}
就这样。这就是您需要的所有代码。它会自动最大限度地利用线程来完成任务。类似于?任务!=线您可以在一个线程上运行数千个任务。对于异步工作流,您不希望线程数超过核心数-您希望线程数尽可能少。@CoryNelson您不希望线程数超过核心数-陈词滥调。如果我的所有线程都被某个IO磁盘(NW)阻塞,为什么我不在所有内核都空闲时创建一个新的线程呢?@Eser,如我所说,用于异步工作流。您不应该在async中有任何阻塞I/O。@supersausage007在发送新的ping之前,您不必等待上一个ping的应答。这就是为什么在链接的示例中有一个线程专门用于发送它们,还有一个线程专门用于读取回复。谢谢你,你的代码工作得很好,当然比我的解决方案更优雅。对于一些人来说,一个警告可能是需要.NET 4.6或更高版本才能通过GNuGet安装System.Reactive.Linq。就性能而言,我的原始解决方案和您更优雅的解决方案在+4500 IP上都是相同的2300毫秒,ping超时为1500ms-非常有效:我将您的贡献标记为答案,因为您的代码更优雅简洁。
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;
}
}
}