为什么重新启动进程时不再收到输出数据接收事件
本文关键字:输出 数据 事件 为什么 进程 不再 重新启动 | 更新日期: 2023-09-27 18:36:22
我有一个 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);
}
}
}
}
尝试使用:
private void OnProcessExited(object sender, EventArgs e)
{
if (_process != null)
{
Thread.Sleep(2000);
_process.CancelOutputRead();
_process.CancelErrorRead();
_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();
}
}
附言
简短描述:输出读取和错误读取关闭,进程重新启动。
带有反射代码的详细说明:
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;
[..]
}
选项 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
在阅读了进程类上的 MSDN 后,我相信这段摘录解释了这个问题
事件指示关联的进程具有 写入其重定向的标准错误流。
该事件仅在异步读取操作期间发生 标准错误。若要启动异步读取操作,必须 重定向进程的标准错误流,添加事件处理程序 到 ErrorDataReceived 事件,并调用 BeginErrorReadLine。 此后,每次进程时,ErrorDataReceived 事件都会发出信号 将一行写入重定向的标准错误流,直到 进程退出或调用 CancelErrorRead。
MSDN 链接
所以你应该只需要在你的退出处理代码中这样做
_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();