我有以下函数,它以异步流的形式返回标准输出数据,该数据由运行System.Diagnostics.Process
. 当前方法中的所有内容都按预期工作;我可以在一个循环中调用它,await foreach()
我得到的每一行输出都是由外部 exe 生成的。
private static async IAsyncEnumerable<string> ProcessAsyncStream (
ProcessStartInfo processStartInfo)
{
// Ensure that process is destroyed when this method exits
using var process = new Process() { StartInfo = processStartInfo };
// Buffer used to pass data from event-handler back to this method
BufferBlock<string> dataBuffer = new BufferBlock<string>();
process.OutputDataReceived += (s, e) =>
{
if (e.Data is null)
{
dataBuffer.Complete();
}
else
{
dataBuffer.Post(e.Data);
}
};
// Start process and redirect output streams
process.Start();
process.BeginOutputReadLine();
// Return data line by line
while (await dataBuffer.OutputAvailableAsync())
yield return dataBuffer.Receive();
}
我的问题是现在我需要它来返回标准输出和标准错误结果。我创建了这个类来保存每个流中的数据。
public class ProcessData
{
public string Error { get; set; } = "";
public string Output { get; set; } = "";
}
并变成ProcessAsyncStream()
了这样
private static async IAsyncEnumerable<ProcessData> ProcessAsyncStream (
ProcessStartInfo processStartInfo)
{
// Ensure that process is destroyed when this method exits
using var process = new Process() { StartInfo = processStartInfo };
// Buffer used to pass data from event-handlers back to this method
BufferBlock<string> outputDataBuffer = new BufferBlock<string>();
BufferBlock<string> errorDataBuffer = new BufferBlock<string>();
process.OutputDataReceived += (s, e) =>
{
if (e.Data is null)
{
outputDataBuffer.Complete();
}
else
{
outputDataBuffer.Post(e.Data);
}
};
process.ErrorDataReceived += (s, e) =>
{
if (e.Data is null)
{
errorDataBuffer.Complete();
}
else
{
errorDataBuffer.Post(e.Data);
}
};
// Start process and redirect output streams
process.Start();
process.BeginOutputReadLine();
// Return data line by line
while (await outputDataBuffer.OutputAvailableAsync()
|| await errorDataBuffer.OutputAvailableAsync())
yield return new ProcessData()
{
Error = errorDataBuffer.Receive(),
Output = outputDataBuffer.Receive()
}
}
问题是,如果任何一个缓冲区在另一个缓冲区完成之前完成,而不是该方法挂起,因为该缓冲区.Receive()
没有任何数据要接收。如果我将while
条件更改为&&
then 我将不会从另一个缓冲区获取所有数据。
有什么建议么?