С помощью 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 потоков.
Любая помощь будет принята с благодарностью, поэтому большое спасибо всем за внимание!