Я пытаюсь создать простой класс, который вызывает функцию перезагрузки в зависимости от типа машины, которая будет перезагружена.Вызываемые методы ссылаются на библиотеку, которая содержит общедоступные статические методы.Я хочу асинхронно вызывать эти статические методы, используя Task для параллельного вызова методов перезагрузки.Вот код на данный момент:
РЕДАКТИРОВАТЬ По запросу сообщества, это теперь версия того же вопроса, с кодом ниже компиляции.Обратите внимание, что вам нужна Renci.SshNet lib, а также необходимо установить ссылки на нее в вашем проекте.
// libs
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using Renci.SshNet;
namespace ConsoleApp
{
class Program
{
// Simple Host class
public class CHost
{
public string IP;
public string HostType;
public CHost(string inType, string inIP)
{// constructor
this.IP = inIP;
this.HostType = inType;
}
}
// Call test function
static void Main(string[] args)
{
// Create a set of hosts
var HostList = new List<CHost>();
HostList.Add( new CHost("Machine1", "10.52.0.93"));
HostList.Add( new CHost("Machine1", "10.52.0.30"));
HostList.Add( new CHost("Machine2", "10.52.0.34"));
// Call async host reboot call
RebootMachines(HostList);
}
// Reboot method
public static async void RebootMachines(List<CHost> iHosts)
{
// Locals
var tasks = new List<Task>();
// Build list of Reboot calls - as a List of Tasks
foreach(var host in iHosts)
{
if (host.HostType == "Machine1")
{// machine type 1
var task = CallRestartMachine1(host.IP);
tasks.Add(task); // Add task to task list
}
else if (host.HostType == "Machine2")
{// machine type 2
var task = CallRestartMachine2(host.IP);
tasks.Add(task); // Add task to task list
}
}
// Run all tasks in task list in parallel
await Task.WhenAll(tasks);
}
// ASYNC METHODS until here
private static async Task CallRestartMachine1(string host)
{// helper method: reboot machines of type 1
// The compiler complains here (RebootByWritingAFile is a static method)
// Error: "This methods lacks await operators and will run synchronously..."
RebootByWritingAFile(@"D:\RebootMe.bm","reboot");
}
private static async Task CallRestartMachine2(string host)
{// helper method: reboot machines of type 2
// The compiler warns here (RebootByWritingAFile is a static method)
// Error: "This methods lacks await operators and will run synchronously..."
RebootByNetwork(host,"user","pwd");
}
// STATIC METHODS here, going forward
private static void RebootByWritingAFile(string inPath, string inText)
{// This method does a lot of checks using more static methods, but then only writes a file
try
{
File.WriteAllText(inPath, inText); // static m
}
catch
{
// do nothing for now
}
}
private static void RebootByNetwork(string host, string user, string pass)
{
// Locals
string rawASIC = "";
SshClient SSHclient;
SshCommand SSHcmd;
// Send reboot command to linux machine
try
{
SSHclient = new SshClient(host, 22, user, pass);
SSHclient.Connect();
SSHcmd = SSHclient.RunCommand("exec /sbin/reboot");
rawASIC = SSHcmd.Result.ToString();
SSHclient.Disconnect();
SSHclient.Dispose();
}
catch
{
// do nothing for now
}
}
}
}
Моя единственная проблема с этой настройкой на данный момент заключается в том, что статическийметоды вызываются немедленно (последовательно) и не назначаются задаче.Например, строка
...
else if (host.HostType == "Machine2")
{// machine type 2
var task = CallRestartMachine2(host.IP);
tasks.Add(task); // Add task to task list
}
...
выполняется в течение 20 секунд, если хост недоступен.Если 10 хостов недоступны, последовательная продолжительность составляет 20 * 10 = 200 секунд.
Мне известны некоторые, казалось бы, похожие вопросы, такие как
Однако приведенные лямбда-выражения по-прежнему оставляют меня с той же ошибкой компилятора [«В этих методах отсутствуют операторы ожидания ...»].Кроме того, я не хочу порождать явные потоки (новый Thread (() => ...)) из-за высоких издержек при перезапуске большого количества компьютеров в кластере.
Возможно, мне потребуется перезагрузитьбольшое количество машин в кластере.Отсюда мой вопрос: Как я могу изменить свою конструкцию, чтобы иметь возможность параллельно вызывать вышеупомянутые статические методы ?
EDIT Благодаря комментариям @JohanPи @MickyD, я хотел бы пояснить, что я на самом деле пытался написать асинхронную версию обоих статических методов.Тем не менее, это приводит меня в кроличью нору, где каждый раз, когда статический метод вызывается в асинхронном методе, я получаю предупреждение компилятора о том, что вызов будет синхронным.Вот пример того, как я пытался обернуть вызов метода как асинхронную задачу, надеясь вызвать зависимые методы асинхронным способом.
private static async Task CallRestartMachine1(string host)
{// helper method: reboot machines of type 1
// in this version, compiler underlines '=>' and states that
// method is still called synchronously
var test = await Task.Run(async () =>
{
RebootByWritingAFile(host);
});
}
Есть ли способ обернуть вызов статического метода, такойчто все статические дочерние методы не нужно переписывать как асинхронные?
Заранее всем спасибо.