C#处理实时标准输出流



我正试图使用Process从我的C#项目中调用rclone,并且还需要从进程中获得实时输出。

为了实现这一点,我使用了以下代码,如下所示:

它是从这个岗位上取下来的。

using System;
using System.IO;
namespace Collection_Manager
{
/// <summary>
/// Stream reader for StandardOutput and StandardError stream readers
/// Runs an eternal BeginRead loop on the underlaying stream bypassing the stream reader.
/// 
/// The TextReceived sends data received on the stream in non delimited chunks. Event subscriber can
/// then split on newline characters etc as desired.
/// </summary>
class AsyncStreamReader
{
public delegate void EventHandler<args>(object sender, string Data);
public event EventHandler<string> DataReceived;
protected readonly byte[] buffer = new byte[4096];
private StreamReader reader;

/// <summary>
///  If AsyncStreamReader is active
/// </summary>
public bool Active { get; private set; }

public void Start()
{
if (!Active)
{
Active = true;
BeginReadAsync();
}
}

public void Stop()
{
Active = false;
}

public AsyncStreamReader(StreamReader readerToBypass)
{
reader = readerToBypass;
Active = false;
}

protected void BeginReadAsync()
{
if (Active)
{
reader.BaseStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), null);
}
}
private void ReadCallback(IAsyncResult asyncResult)
{
int bytesRead = reader.BaseStream.EndRead(asyncResult);
string data = null;
//Terminate async processing if callback has no bytes
if (bytesRead > 0)
{
data = reader.CurrentEncoding.GetString(buffer, 0, bytesRead);
}
else
{
//callback without data - stop async
Active = false;
}
//Send data to event subscriber - null if no longer active
if (DataReceived != null)
{
DataReceived.Invoke(this, data);
}
//Wait for more data from stream
BeginReadAsync();
}

}
}

我用这个来称呼它:

logHandler.writeLogToBuffer();
uploadProcess.StartInfo.UseShellExecute = false;
uploadProcess.StartInfo.CreateNoWindow = true;            uploadProcess.StartInfo.RedirectStandardOutput = true;
uploadProcess.StartInfo.FileName = "rclone.exe";
uploadProcess.StartInfo.StandardOutputEncoding = Encoding.UTF8;
uploadProcess.StartInfo.Arguments =
"sync -P " +
""" + sourceDirectory + "" " +
""" + Properties.Settings.Default.remoteName + "/" + destination + "" " +
"--exclude '.*{/**,}' " +
"--config "" + Properties.Settings.Default.rcloneConfig + "" " +
Properties.Settings.Default.rcloneArgs;
uploadProcess.Start();
AsyncStreamReader stdOut = new AsyncStreamReader(uploadProcess.StandardOutput);
stdOut.DataReceived += (sender, data) =>
{
if (!string.IsNullOrEmpty(data))
{
if (data.Contains("ETA"))
{
logHandler.loadLogFromBuffer();
}
logHandler.writeToLog(data);
}
};
stdOut.Start();

然而,我遇到的问题是,流的第一个字节(来自Transferring:...消息的T(与流的其余部分分开输出。

日志处理程序只是我为UI线程上的WPF richtextbox编写的一个方法。writeToLog(string message);只是在RTB上添加一行,writeLogToBuffer();将日志写入可以加载的缓冲区,以便用loadLogFromBuffer();将RTB内容加载回。

那么,这里的问题是什么?这是rclone的怪癖吗?我该如何解决这个问题?提前感谢!

您可以在Process中使用EnableRaisingEvents属性。将其设置为true并调用BeginOutputReadLine((方法以启动输出侦听。然后您就可以使用OutputDataReceived事件了。每当数据进入时,都会触发此事件。

最新更新