[Mono-list] System.Diagnostic.Process and event handlers

noda www.bgr at free.fr
Sat Jan 29 13:23:22 EST 2011


I'm not doing anything fancy, here's some code:

- This is the class I use to start external programs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;

namespace myapp
{
    class ExternalProgram
    {
        // Events
        public delegate void ExternalProgramEventHandler(string newLine);
        public event ExternalProgramEventHandler ProgramFinished;
        public event ExternalProgramEventHandler ProgramStarted;
        public event ExternalProgramEventHandler ProgramOutputReceived;

        // Variables
        public bool DebugOutput = false;
        private string path = null;
        public string args = null;
        private Process proc = null;
        private ProcessPriorityClass priority = ProcessPriorityClass.Normal;

        #region Init

        public ExternalProgram(string path, string args, int priority)
        {
            this.path = path;
            this.args = args;

            switch (priority)
            {
                case 0: this.priority = ProcessPriorityClass.Idle; break;
                case 2: this.priority = ProcessPriorityClass.High; break;
                default: this.priority = ProcessPriorityClass.Normal; break;
            }
        }

        #endregion

        #region Start/stop

        public void Start()
        {
            doWork();
        }

        public void StartThreaded()
        {
            try
            {
                Thread worker = new Thread(doWork);
                worker.Start();
            }
            catch (Exception)
            { }
        }

        public void Stop()
        {
            try
            {
                if (proc != null)
                    proc.Kill();
            }
            catch (Exception)
            { }
        }

        private void doWork()
        {
            try
            {
                proc = new Process();
                proc.StartInfo.FileName =
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
path);
                proc.StartInfo.WorkingDirectory =
Path.GetDirectoryName(proc.StartInfo.FileName);
                proc.StartInfo.Arguments = args;
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.CreateNoWindow = true;

                proc.ErrorDataReceived += new
System.Diagnostics.DataReceivedEventHandler(proc_DataReceived);
                proc.OutputDataReceived += new
System.Diagnostics.DataReceivedEventHandler(proc_DataReceived);

                if (ProgramOutputReceived != null)
                    ProgramOutputReceived(proc.StartInfo.FileName + " " +
proc.StartInfo.Arguments);

                proc.Start();
                proc.BeginErrorReadLine();
                proc.BeginOutputReadLine();
                proc.PriorityClass = priority;

                if (ProgramStarted != null)
                    ProgramStarted(null);

                proc.WaitForExit();				
				proc.CancelOutputRead();
				proc.CancelErrorRead();
                proc.Close();
                proc = null;

                if (ProgramFinished != null)
                    ProgramFinished(null);
            }
            catch (Exception e)
            {
                Log.WriteLine("External program '" + path + "' error:" +
e.Message);
            }
        }

        private void proc_DataReceived(object sender, DataReceivedEventArgs
line)
        {
            try
            {
                if (line != null)
                {
                    if (DebugOutput)
                        Log.WriteLine(line.Data);

                    if (ProgramOutputReceived != null)
                        ProgramOutputReceived(line.Data);
                }
            }
            catch (Exception)
            { }
        }

        #endregion
    }
}
-------------------------------------------------------------------

An here is how I use it in my main program:

string args = generateEncArgs(options, profiles, subs, tempPath);
ExternalProgram mencoder = new ExternalProgram(config.mencoderPath, args,
priority);
mencoder.ProgramOutputReceived += new
ExternalProgram.ExternalProgramEventHandler(external_OutputReceived);
mencoder.ProgramOutputReceived += new
ExternalProgram.ExternalProgramEventHandler(mencoder_OutputReceived);
mencoder.Start();

And here are the event handlers:

        private static void external_OutputReceived(string line)
        {
            if (logWriter != null)
                logWriter.WriteLine(line);
        }

        private static void mencoder_OutputReceived(string line)
        {
            try
            {
                if (line != null)
                {
                    if (line.StartsWith("Pos:"))
                    {
                        // Pos:   1.0s     24f ( 0%) 23.41fps Trem:   0min  
0mb  A-V:0.053 [0:133]
                        string infoPattern = ".*\\( *([0-9]+%)\\)
*([0-9.]+)fps Trem: *([0-9]+min).*";
                        Regex regex = new Regex(infoPattern,
RegexOptions.IgnoreCase);
                        if (regex.IsMatch(line))
                            Console.Write(regex.Replace(line, "\rEncoding:
completed=$1 fps=$2 remaining=$3        "));
					}
                }
            }
            catch (Exception)
            { }
        }

The problem seems really strange, the event handler for mencoder is called a
few times during like half a second, then nothing until the encoding is
complete (and then all events comes at the same time).

Even stranger, sometimes the program just get stuck indefinitely...

Thanks for your help.
-- 
View this message in context: http://mono.1490590.n4.nabble.com/System-Diagnostic-Process-and-event-handlers-tp3246096p3246428.html
Sent from the Mono - General mailing list archive at Nabble.com.


More information about the Mono-list mailing list