Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何异步调用静态方法_C#_Asynchronous_Task - Fatal编程技术网

C# 如何异步调用静态方法

C# 如何异步调用静态方法,c#,asynchronous,task,C#,Asynchronous,Task,我试图构造一个简单的类,它根据要重新启动的机器类型调用重新启动函数。被调用的方法引用包含公共静态方法的库。我想使用Task异步调用这些静态方法,以便并行调用reboot方法。以下是迄今为止的代码: 编辑 根据社区的要求,这是同一问题的一个版本,下面的代码正在编译。请不要告诉我您需要lib,还需要在项目中设置对它的引用 // libs using System.IO; using System.Threading.Tasks; using System.Collections.Generic;

我试图构造一个简单的类,它根据要重新启动的机器类型调用重新启动函数。被调用的方法引用包含公共静态方法的库。我想使用Task异步调用这些静态方法,以便并行调用reboot方法。以下是迄今为止的代码:

编辑 根据社区的要求,这是同一问题的一个版本,下面的代码正在编译。请不要告诉我您需要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
            }
        }




    }
}
如果无法访问主机,则需要20秒执行。如果无法访问10台主机,则顺序持续时间为20*10=200秒

我知道一些看似相似的问题,例如

但是,引用的lambda表达式仍然给我留下了相同的编译器错误[此方法缺少等待运算符…]。另外,我不想产生显式线程new Thread=>。。。如果在群集中重新启动大量计算机,会导致高开销

我可能需要重新启动集群中的大量计算机。因此,我的问题是:如何更改构造以便能够并行调用上述静态方法

编辑 感谢@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);
    });

}
有没有办法包装静态方法调用,使所有静态子方法都不需要重写为异步


提前感谢大家。

您的代码奇怪地混合了异步和连续,甚至无法编译。你需要让它一直异步。当你调用重启机器时。。。而且这个调用不能等待,您可以在该调用上安排继续,即重新启动计算机…ContinueWitht=>Console.WriteLine'All Done'


您的代码奇怪地混合了异步和连续,甚至无法编译。你需要让它一直异步。当你调用重启机器时。。。而且这个调用不能等待,您可以在该调用上安排继续,即重新启动计算机…ContinueWitht=>Console.WriteLine'All Done'


我认为您应该重新考虑线程的高开销:与网络往返和每次RPC调用的等待时间相比,这种开销是可以忽略的。我很确定,创建N个线程所需的资源与运行N个网络请求所需的资源相比是微不足道的,无论是http[s]、RPC还是其他什么

我的方法是将任务排队到线程安全集合ConcurrentQueue、ConcurrentBag和friends中,然后生成有限数量的线程,在这些工作项中循环,直到集合为空并刚刚结束


这不仅允许您并行运行任务,还允许您以受控的并行方式运行它们。

我认为您应该重新考虑线程的高开销:与网络往返和每次RPC调用的等待时间相比,此开销是不可忽略的。我很确定,创建N个线程所需的资源与运行N个网络请求所需的资源相比是微不足道的,无论是http[s]、RPC还是其他什么

我的方法是将任务排队到线程安全集合ConcurrentQueue、ConcurrentBag和friends中,然后生成有限数量的线程,在这些工作项中循环,直到集合为空并刚刚结束


这不仅允许您并行运行任务,还允许您以受控的并行方式运行任务。

各位,感谢您的输入和帮助。在过去的几天里,我一直在研究他的方法,并提出了以下异步调用静态方法的方法:

// 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

            await Task.Run(() =>
            {
                RebootByWritingAFile(@"D:\RebootMe.bm", "reboot");
            });

        }
        private static async Task CallRestartMachine2(string host)
        {// helper method: reboot machines of type 2

            await Task.Run(() =>
            {
                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
            }
        }




    }
}

此安装程序异步调用我的静态方法。我希望这能帮助那些遇到类似问题的人。再次感谢您的投入。

各位,感谢您的投入和帮助。在过去的几天里,我一直在研究他的方法,并提出了以下异步调用静态方法的方法:

// 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

            await Task.Run(() =>
            {
                RebootByWritingAFile(@"D:\RebootMe.bm", "reboot");
            });

        }
        private static async Task CallRestartMachine2(string host)
        {// helper method: reboot machines of type 2

            await Task.Run(() =>
            {
                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
            }
        }




    }
}

此安装程序异步调用我的静态方法。我希望这能帮助那些遇到类似问题的人。再次感谢您的所有输入。

如何并行运行多个方法?通过在不同的线程中运行它们。你不喜欢线吗?重新编写异步方法并等待它们。此代码甚至不会编译,因此我们很难帮助您,因为这显然不是您的代码外观like@Dave,代码现在在安装和引用库后即可编译。如何并行运行多个方法?通过在不同的线程中运行它们
s你不喜欢线吗?重新编写异步方法并等待它们。此代码甚至不会编译,因此我们很难帮助您,因为这显然不是您的代码外观like@Dave,代码现在会在安装和引用库后编译。回答得好。我要补充的唯一一点是,现在这些方法是异步的,或者您已经创建了其他异步方法,通常最好使用异步后缀重命名它们。谢谢大家的意见。我编辑了我的问题,以显示除了简单的代码构造之外我还尝试了什么。实际上,如果每次调用都在一个新线程上调用这些方法,我最终会执行准异步执行,但会有显式的线程切换开销。@JohanP,一旦安装并引用Renci.SHH lib,代码现在就可以编译了。回答得好。我要补充的唯一一点是,现在这些方法是异步的,或者您已经创建了其他异步方法,通常最好使用异步后缀重命名它们。谢谢大家的意见。我编辑了我的问题,以显示除了简单的代码构造之外我还尝试了什么。本质上,如果我每次调用都在一个新线程上调用这些方法,我最终会得到一个准异步执行,但会有显式的线程切换开销。@JohanP,一旦安装并引用Renci.SHH lib,代码现在就可以编译了。这个开销是IMHO negigable-OP谈论的是新线程,而不是线程池线程。产生显式线程有一个可测量的成本,大约。此外,无论您使用显式线程还是线程池线程,这些线程都没有做任何有用的事情。因此,除了开销事实上不可忽略之外,他们仍然没有完成任何事情。@Eugen Rieck,谢谢你的投入。我将使用这种方法作为最后手段。但是,一般指南建议不要在每个CPU核心上使用超过50个线程,因为这样会积累太多的线程切换开销。我有另一种方法,我在不到5秒钟的时间内扫描本地服务器网络上的数万个IP地址,全部在一个异步调用中完成。这就是我试图实现的,但是调用lib静态方法仍然只能强制执行同步。另一个很好的区别是,为什么我不应该使用多线程,而应该使用多任务,这很好地解释了@MickyD 1MB/线程是可忽略的,如果您将其与通过SMB进行RPC调用所需的12MB进行比较,那么这个开销就是IMHO NERGLIGABLE-OP所说的新线程,而不是线程池线程。产生显式线程有一个可测量的成本,大约。此外,无论您使用显式线程还是线程池线程,这些线程都没有做任何有用的事情。因此,除了开销事实上不可忽略之外,他们仍然没有完成任何事情。@Eugen Rieck,谢谢你的投入。我将使用这种方法作为最后手段。但是,一般指南建议不要在每个CPU核心上使用超过50个线程,因为这样会积累太多的线程切换开销。我有另一种方法,我在不到5秒钟的时间内扫描本地服务器网络上的数万个IP地址,全部在一个异步调用中完成。这就是我要实现的,但是调用lib静态方法只会强制同步执行。另外一个很好的区别是,如果您将它与通过SMB进行RPC调用所需的12MB进行比较,那么解释了为什么我不应该使用多个线程,而是多任务处理的另一个好区别。
// 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

            await Task.Run(() =>
            {
                RebootByWritingAFile(@"D:\RebootMe.bm", "reboot");
            });

        }
        private static async Task CallRestartMachine2(string host)
        {// helper method: reboot machines of type 2

            await Task.Run(() =>
            {
                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
            }
        }




    }
}