我有以下用例。我已经从Unmanned C++中创建了一个EXE。假设在控制台上打印1-100。输出捕获到下面的输出回调中
List<int> a = new List<int>();
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
a.add(Convert.ToInt(e.Data));
}
但是我想使用IEnumerable并产生e.Data的 yield 。考虑到C++ exe将拥有它自己的执行线程,因此它不会等待它提供控件。我将不得不等待执行完成。我可以捕获所有内容并准备一个列表。然后我可以一件一件地生产物品。我对您的问题是,在进程运行时,是否有任何已知的机制或方法来执行此操作?我可以在C++代码中进行哪些更改?这样我才能来回控制它?考虑此过程在C#端的一个功能下运行。
最佳答案
下一种方法可用于在外部进程运行时读取其输出:
var proc = new Process
{
StartInfo =
{
FileName = "process_name.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
},
// Set this property to true to enable external
// process raise notification that is has exited.
EnableRaisingEvents = true
};
// BlockingCollection is a thread safe producer-consumer
// collection. We use it to collect the output of the
// external process and to process it while the process
// is running.
var lines = new BlockingCollection<string>();
proc.OutputDataReceived += (s, e) =>
{
// Here we collect the output of the external process.
if (!string.IsNullOrEmpty(e.Data))
lines.Add(e.Data);
};
// This event is raised when external process exits.
proc.Exited += (s, e) =>
{
// Here we notify our BlockingCollection that no more
// data to process is available.
lines.CompleteAdding();
};
proc.Start();
proc.BeginOutputReadLine();
// Here we start to process the output of the external process
// without waiting for it to exit.
// This loop iterates over the items produced by the
// BlockingCollection until method CompleteAdding is called.
// This loop is being executed while external process is
// running and finishes when the process exits.
foreach (string line in lines.GetConsumingEnumerable())
{
Console.WriteLine(line);
}
// Here we do not need to call proc.WaitForExit(), because
// loop over lines collection finishes when proc exits.
这里是学习了解此代码示例的链接:
Process.EnableRaisingEvents
Process.Exited
BlockingCollection
BlockingCollection.CompleteAdding
BlockingCollection.GetConsumingEnumerable
为了方便起见,我们可以创建一个方法来启动外部流程,并立即返回
IEnumerable
对象,该对象可用于循环处理流程的输出数据:private static IEnumerable<string> ReadOutput(string procFileName)
{
var proc = new Process
{
StartInfo =
{
FileName = procFileName,
UseShellExecute = false,
RedirectStandardOutput = true,
},
EnableRaisingEvents = true
};
var lines = new BlockingCollection<string>();
proc.OutputDataReceived += (s, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
lines.Add(e.Data);
};
proc.Exited += (s, e) =>
{
lines.CompleteAdding();
};
proc.Start();
proc.BeginOutputReadLine();
return lines.GetConsumingEnumerable();
}
然后,当需要运行外部进程并在输出数据可用时立即读取其输出时,可以使用此方法:
public static void Demo()
{
foreach (string line in ReadOutput("process_name.exe"))
{
Console.WriteLine(line);
}
}
关于c# - 如何将IEnumerable与Process.Start的输出事件处理程序一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61771084/