Почему мой сервис windows вращается вокруг ядра процессора - PullRequest
0 голосов
/ 24 января 2020

Я создал службу Windows, которая является оболочкой для консольного приложения. Функционально он работает правильно, запуская и останавливая приложение с сохранением состояния. Единственная проблема, которую я заметил, заключается в том, что служба будет работать на 1 ядре на 100%. Кажется, он не вращает процессор при запуске его в режиме отладки VS2019, поэтому я не вижу причины, пытаясь отладить код. Это очень простая программа, которая использует Topshelf для создания сервиса windows. Я включил здесь два файла программы:

class Program
    {
        static void Main(string[] args)
        {

            var rc = HostFactory.Run(x =>                                   
            {
                x.Service<BedrockServiceWrapper>(s =>                                  
                {
                    s.ConstructUsing(name => new BedrockServiceWrapper());                
                    s.WhenStarted(tc => tc.Start());                         
                    s.WhenStopped(tc => tc.Stop()); 


                });
                x.RunAsNetworkService();                                       

                x.SetDescription("Windows Service Wrapper for Windows Bedrock Server");                   
                x.SetDisplayName("BedrockService");                                  
                x.SetServiceName("BedrockService");                                  
            });                                                             

            var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());  
            Environment.ExitCode = exitCode;
        }
    }

и

public class BedrockServiceWrapper
    {

        Process process;
        Thread outputThread;
        Thread errorThread;
        Thread inputThread;
        static BackgroundWorker bedrockServer;
        string exePath;

        public BedrockServiceWrapper()
        {
            exePath = ConfigurationManager.AppSettings["BedrockServerExeLocation"];
            bedrockServer = new BackgroundWorker
            {
                WorkerSupportsCancellation = true
            };

        }


        public void Stop()
        {

            process.StandardInput.WriteLine("stop");            
            bedrockServer.CancelAsync();

        }



        public void Start()
        {

            bedrockServer.DoWork += (s, e) =>
            {

                    RunServer(exePath);

            };

            bedrockServer.RunWorkerAsync();

        }

        public void RunServer(string path)
        {


            // Fires up a new process to run inside this one
            process = Process.Start(new ProcessStartInfo
            {
                UseShellExecute = false,

                RedirectStandardError = true,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                WindowStyle = ProcessWindowStyle.Hidden,
                FileName = path



            });

            // Depending on your application you may either prioritize the IO or the exact opposite
            const ThreadPriority ioPriority = ThreadPriority.Highest;
            outputThread = new Thread(outputReader) { Name = "ChildIO Output", Priority = ioPriority };
            errorThread = new Thread(errorReader) { Name = "ChildIO Error", Priority = ioPriority };
            inputThread = new Thread(inputReader) { Name = "ChildIO Input", Priority = ioPriority };

            // Set as background threads (will automatically stop when application ends)
            outputThread.IsBackground = errorThread.IsBackground
                = inputThread.IsBackground = true;

            // Start the IO threads
            outputThread.Start(process);
            errorThread.Start(process);
            inputThread.Start(process);

            process.WaitForExit();

        }

        /// <summary>
        /// Continuously copies data from one stream to the other.
        /// </summary>
        /// <param name="instream">The input stream.</param>
        /// <param name="outstream">The output stream.</param>
        private static void passThrough(Stream instream, Stream outstream)
        {
            byte[] buffer = new byte[4096];
            while (true)
            {
                int len;
                while ((len = instream.Read(buffer, 0, buffer.Length)) > 0)
                {

                    outstream.Write(buffer, 0, len);
                    outstream.Flush();
                }
            }
        }

        private static void outputReader(object p)
        {
            var process = (Process)p;
            // Pass the standard output of the child to our standard output
            passThrough(process.StandardOutput.BaseStream, Console.OpenStandardOutput());
        }

        private static void errorReader(object p)
        {
            var process = (Process)p;
            // Pass the standard error of the child to our standard error
            passThrough(process.StandardError.BaseStream, Console.OpenStandardError());
        }

        private static void inputReader(object p)
        {
            var process = (Process)p;
            // Pass our standard input into the standard input of the child
            passThrough(Console.OpenStandardInput(), process.StandardInput.BaseStream);
        }
    }

Может ли это быть что-то, связанное с потоками, копирующими входы и выходы между потоками? Я не верю, что о них много писали, но, возможно, это просто попытка скопировать множество фрагментов потока нулевой длины?

Github: https://github.com/ravetroll/BedrockService

...