Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.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# 为什么重新启动进程时不再接收OutputDataReceived事件?_C#_Console Application - Fatal编程技术网

C# 为什么重新启动进程时不再接收OutputDataReceived事件?

C# 为什么重新启动进程时不再接收OutputDataReceived事件?,c#,console-application,C#,Console Application,我有一个ChildProcessMonitor类,它启动进程,报告接收到的数据,并在进程退出时重新启动进程。我的问题是,一旦进程退出并再次调用Start,就不再报告输出 using System; using System.Diagnostics; using System.IO; using System.Threading; namespace WcfClient { /// <summary> /// Can be used to launch and mon

我有一个ChildProcessMonitor类,它启动进程,报告接收到的数据,并在进程退出时重新启动进程。我的问题是,一旦进程退出并再次调用Start,就不再报告输出

using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace WcfClient
{
    /// <summary>
    /// Can be used to launch and monitor (restart on crash) the child process.
    /// </summary>
    public class ChildProcessMonitor
    {
        private Process _process;

        /// <summary>
        /// Starts and monitors the child process.
        /// </summary>
        /// <param name="fullProcessPath">The full executable process path.</param>
        public void StartAndMonitor(string fullProcessPath)
        {
            StartAndMonitor(fullProcessPath, null);
        }

        /// <summary>
        /// Starts and monitors the child process.
        /// </summary>
        /// <param name="fullProcessPath">The full executable process path.</param>
        /// <param name="arguments">The process arguments.</param>
        public void StartAndMonitor(string fullProcessPath, string arguments)
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo
            {
                CreateNoWindow = true,
                FileName = fullProcessPath,
                WorkingDirectory = Path.GetDirectoryName(fullProcessPath) ?? string.Empty,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };

            processStartInfo.Arguments = arguments;             

            _process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true };
            _process.OutputDataReceived += OnOutputDataReceived;
            _process.ErrorDataReceived += OnErrorDataReceived;
            _process.Start();
            _process.BeginOutputReadLine();
            _process.BeginErrorReadLine();
            _process.Exited += OnProcessExited;
        }

        /// <summary>
        /// Called when process exits.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OnProcessExited(object sender, EventArgs e)
        {
            if (_process != null)
            {
                Thread.Sleep(2000);                 
                _process.Start();                       
            }
        }

        /// <summary>
        /// The ErrorDataReceived event indicates that the associated process has written to its redirected StandardError stream.
        /// </summary>
        public DataReceivedEventHandler ErrorDataReceived;

        /// <summary>
        /// Called when error data received.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Diagnostics.DataReceivedEventArgs"/> instance containing the event data.</param>
        private void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            Trace.WriteLine("Error data.");
            if (ErrorDataReceived != null)
            {
                ErrorDataReceived(sender, e);
            }
        }

        /// <summary>
        /// The OutputDataReceived event indicates that the associated Process has written to its redirected StandardOutput stream.
        /// </summary>
        public DataReceivedEventHandler OutputDataReceived;

        /// <summary>
        /// Called when output data received.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Diagnostics.DataReceivedEventArgs"/> instance containing the event data.</param>
        private void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            Trace.WriteLine("Output data.");
            if (OutputDataReceived != null)
            {
                OutputDataReceived(sender, e);
            }
        }

    }

}
使用系统;
使用系统诊断;
使用System.IO;
使用系统线程;
命名空间WcfClient
{
/// 
///可用于启动和监视(崩溃时重新启动)子进程。
/// 
公共类ChildProcessMonitor
{
私有进程(u进程),;
/// 
///启动并监视子进程。
/// 
///完整的可执行进程路径。
public void StartAndMonitor(字符串fullProcessPath)
{
StartAndMonitor(fullProcessPath,null);
}
/// 
///启动并监视子进程。
/// 
///完整的可执行进程路径。
///过程参数。
public void StartAndMonitor(字符串fullProcessPath、字符串参数)
{
ProcessStartInfo ProcessStartInfo=新的ProcessStartInfo
{
CreateNoWindow=true,
FileName=fullProcessPath,
WorkingDirectory=Path.GetDirectoryName(fullProcessPath)??string.Empty,
UseShellExecute=false,
重定向标准输出=真,
重定向标准错误=true
};
processStartInfo.Arguments=参数;
_进程=新进程{StartInfo=processStartInfo,EnableRaisingEvents=true};
_process.OutputDataReceived+=OnOutputDataReceived;
_process.ErrorDataReceived+=OneErrorDataReceived;
_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();
_process.Exited+=OnProcessExited;
}
/// 
///当进程退出时调用。
/// 
///发送者。
///包含事件数据的实例。
私有void onProcessExit(对象发送方,事件参数e)
{
如果(_进程!=null)
{
《睡眠》(2000年);
_process.Start();
}
}
/// 
///ErrorDataReceived事件表示关联进程已写入其重定向的StandardError流。
/// 
公共数据接收Deventhandler ErrorDataReceived;
/// 
///收到错误数据时调用。
/// 
///发送者。
///包含事件数据的实例。
private void OnErrorDataReceived(对象发送方,DataReceivedEventArgs e)
{
Trace.WriteLine(“错误数据”);
如果(ErrorDataReceived!=null)
{
ErrorDataReceived(发送方,e);
}
}
/// 
///OutputDataReceived事件表示关联进程已写入其重定向的StandardOutput流。
/// 
public DataReceivedEventHandler OutputDataReceived;
/// 
///当接收到输出数据时调用。
/// 
///发送者。
///包含事件数据的实例。
接收到OutputDataReceived(对象发送方,DataReceivedEventArgs e)的私有无效
{
Trace.WriteLine(“输出数据”);
如果(OutputDataReceived!=null)
{
OutputDataReceived(发送方,e);
}
}
}
}

选项1-不起作用

我会尝试这个编辑。它将刷新对象上的事件处理程序

private void OnProcessExited(object sender, EventArgs e)
        {
            if (_process != null)
            {
                Thread.Sleep(2000); 
                _process.OutputDataReceived -= OnOutputDataReceived;
                _process.ErrorDataReceived -= OnErrorDataReceived;
                _process.OutputDataReceived += OnOutputDataReceived;
                _process.ErrorDataReceived += OnErrorDataReceived;                
                _process.Start();                       
            }
        }
选项2

我的下一个想法是建议稍微改变一下设计。将ProcessStartInfo存储在类中,然后在现有进程上发生退出而不是调用Start时,处置它并使用ProcessStartInfo对象创建新进程

选项3

在阅读了有关process类的MSDN之后,我相信这篇摘录解释了这个问题

ErrorDataReceived事件表示关联的进程已 写入其重定向的StandardError流

该事件仅在上的异步读取操作期间发生 标准错误。要启动异步读取操作,必须 重定向进程的StandardError流,添加事件处理程序 返回ErrorDataReceived事件,并调用BeginErrorReadLine。 此后,ErrorDataManager每次处理时都会收到事件信号 将一行写入重定向的StandardError流,直到 进程退出或调用CancelErrorRead

因此,您只需要在退出处理代码中执行此操作

    _process.Start();
    _process.BeginOutputReadLine();
    _process.BeginErrorReadLine();
试用:

private void OnProcessExited(object sender, EventArgs e)
{
  if (_process != null)
  {
    Thread.Sleep(2000);
    _process.CancelOutputRead();
    _process.CancelErrorRead();
    _process.Start();
    _process.BeginOutputReadLine();
    _process.BeginErrorReadLine();

  }
}
ps

简短描述:OutputRead&ErrorRead关闭,进程重新启动

反射代码的详细描述:

public void BeginOutputRead()
{
  [..]
  if (this.output == null)
  {
    [..]                    
    this.output = new AsyncStreamReader(this, baseStream, new UserCallBack(this.OutputReadNotifyUser), this.standardOutput.CurrentEncoding);
  }
}

public void Start()
{   
    this.Close();
    [..]
}

public void Close()
{   
    [..]
    this.output = null;
    this.error = null;
    [..]
}

输出是唯一停止工作的事件,还是您丢失了所有事件(输出、错误、退出)?我丢失了输出和错误,但退出是正常的。您的代码无法工作,您必须再次调用StartAndMonitor()来重新启动进程。\u process.Start()重新启动进程。这只是我没有收到的输出。谢谢。这就是我最后所做的,但它仍然没有回答我的问题,即为什么事件会在原始场景中丢失。感谢选项3中的更新,但是@DarkGray是正确的,我需要先取消输出,然后再尝试再次读取。啊哈!我现在明白了。这回答了我的问题,但我想我还是会使用@Malcom O'Hares选项2。