I
I
iamserge2020-06-11 08:16:12
C++ / C#
iamserge, 2020-06-11 08:16:12

How to get tracked and persistent as a ProcessStartInfo thread in C#?

In general, I launch it like this, setting the settings and parameters:

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

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


But the problem is that it all happens "at once", i.e. I have to wait for the python script to execute. But in fact, I want the script to run for 20 hours and gradually in the timer (every 200 ms) to receive something new about the progress of the script. The script itself simply connects to the server and downloads the data, periodically displaying a line about how much it has downloaded each new time ...

But how to make something controlled out of this ProcessStartInfo? Those. you need to run it somehow differently, but I don’t quite understand how, maybe not even through using. this seems to cause an unnecessary effect for me ... But then how to monitor what is happening? The timer is still quite fast, it is unlikely to be much slower, and turning a large log is hardly appropriate. And it will not be so small, because. a lot of data will be collected in 10 hours ...

I did it according to this example https://www.youtube.com/watch?v=g1VWGdHRkHs but what to do next ... Unclear ...

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
Peter, 2020-06-11
@petermzg

Created a class to track the future process

var process = new Process
        {
            StartInfo = psi 
        };

Assigned asynchronous handlers
process.OutputDataReceived += (sender, args) => Display(args.Data);
process.ErrorDataReceived += (sender, args) => Display(args.Data);

Started the process and reading output streams
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

And then just periodically poll the status
var exited = process.WaitForExit(0);

V
Vladimir Korotenko, 2020-06-11
@firedragon

No way. ProcessStartInfo worked and died. You yourself said you need a flow, so create it.
Better wrap everything in a class where you will pull your script once every 200 ms.

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; }
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question