C# 为什么重新启动进程时不再接收OutputDataReceived事件?
我有一个ChildProcessMonitor类,它启动进程,报告接收到的数据,并在进程退出时重新启动进程。我的问题是,一旦进程退出并再次调用Start,就不再报告输出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
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。