iamserge
@iamserge

Как получить отслеживаемый и постоянный как поток ProcessStartInfo в C#?

В общем то запускаю его так, задав настройки и параметры:

ProcessStartInfo psi = new ProcessStartInfo();
                   
                   // Тут найстройки, параметры и т.п.

                   using (var process = Process.Start(psi))
                    {
                        errors = process.StandardError.ReadToEnd();
                        output = process.StandardOutput.ReadToEnd();
                    }


Но проблема в том, что все это случается "за один раз", то есть мне нужно дождаться выполнения скрипта на python. А на самом деле я хочу скрипт запустить выполняться часов на 20 и постепенно в таймере (каждые 200 мс) получать что то новое о ходе работы скрипта. Сам скрипт просто подключается к серверу и качает данные, периодически выводя строку о том, сколько скачал каждый новый раз ...

Но как сделать из этого ProcessStartInfo нечто контролируемое? Т.е. надо его запустить как то иначе, но я не совсем понимаю как, возможно даже не через using т.к. оный судя по всему и вызывает ненужный мне эффект ... Но как потом мониторить происходящее? Таймер еще доовольно быстрый, вряд ли будет сильно медленнее и ворочать большой лог вряд ли уместно. А он будет не так мал, т.к. за часов 10 соберется очень немало данных ...

Делал по этому приеру https://www.youtube.com/watch?v=g1VWGdHRkHs но как быть далее ... Неопнятно ...
  • Вопрос задан
  • 128 просмотров
Пригласить эксперта
Ответы на вопрос 2
petermzg
@petermzg
Самый лучший программист
Создали класс для отслеживания будующего процесса
var process = new Process
        {
            StartInfo = psi 
        };

Назначили асинхронные обработчики
process.OutputDataReceived += (sender, args) => Display(args.Data);
process.ErrorDataReceived += (sender, args) => Display(args.Data);

Запустили процесс и чтение потоков вывода
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();


А далее просто переодически опрашиваете состояние
var exited = process.WaitForExit(0);
Ответ написан
firedragon
@firedragon
Senior .NET developer
Ни как. ProcessStartInfo отработал и умер. Вы сами сказали вам нужен поток, так и создайте его.
Лучше оберните все в класс, где будете дергать свой скрипт раз в 200 мс.
public class ProcInfo{
public DateTime Start{get; private set;}
public DateTime Stop{get; private set;}
public string Errors{get; private set;}
public string Output{get; private set;}
// .... что то еще
}
var procInfo = new List<ProcInfo>();


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var worker = new Worker();
            worker.Start();
            Thread.Sleep(1000); // тут можно поставить Console.ReadLine(); и  ждать вашего ввода, в общем на ваше усмотрение. 
            Console.ReadLine();
            worker.EmergencyExit();
        }
    }
    public class Worker
    {
        private const string PythonPath = @"C:/Python/Python38-32/python.exe";
        private const string PyScript = @"Load.py";
        private const int Interval = 200;
        private Thread _thread = null;

        private readonly List<ProcInfo> _infos = new List<ProcInfo>();

        private void Run()
        {
            var processInfo = new ProcInfo { Start = DateTime.Now };
            var psi = new ProcessStartInfo
            {
                FileName = PythonPath,
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                Arguments = $"\"{PyScript}\" "/*// опустил для ясности все остальные аргументы*/
            };
            try
            {
                using var process = Process.Start(psi);
                processInfo.Error = process.StandardError.ReadToEnd();
                processInfo.Output = process.StandardOutput.ReadToEnd();
                processInfo.Stop = DateTime.Now;
                _infos.Add(processInfo);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                Thread.Sleep(Interval);// эмулируем работу на самом деле у меня ничего не работает
                processInfo.Error = e.Message;
                processInfo.Stop = DateTime.Now;
                _infos.Add(processInfo);
            }

            var delay = processInfo.Stop - processInfo.Start;
            if (delay.TotalMilliseconds < Interval) Thread.Sleep(Interval - (int)delay.TotalMilliseconds); // скрипт отработал быстрее чем нужно ждем
            Run(); // перезапускаем себя
        }

        public void Start()
        {
            _thread = new Thread(new ThreadStart(Run));
            _thread.Start();
        }

        public void EmergencyExit()
        {
            _thread?.Abort();
        }
    }
    public class ProcInfo
    {
        public DateTime Start { get; set; }
        public DateTime Stop { get; set; }
        public string Output { get; set; }
        public string Error { get; set; }
    }
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы