C#如何无需等待控制台程序退出,实时读取其标准输出?
C# 进程标准输出即时读取问题
问题描述
我有一个C#应用程序app1,用于启动另一个C#控制台应用程序app2并读取其标准输出。当前app1的读取代码如下:
public void read_values_from_app2() { Process_OPCDA = new Process { StartInfo = new ProcessStartInfo { FileName = MTX_OPC_DA_reader_path, Arguments = arguments, UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true } }; Process_OPCDA.Start(); string item_values = Process_OPCDA.StandardOutput.ReadToEnd(); Process_OPCDA.WaitForExit(); }
该代码可正常运行,但由于app2在输出所需数据后,还需执行耗时4-5秒的远程CNC机床断开操作才会退出,导致app1需额外等待该时长才能获取数据。即便app2已输出数据,也因Process.WaitForExit()的存在而延迟获取。移除该语句后则无法读取到任何内容。
app2的代码如下:
static void Main(string[] args) { // 连接远程机床 // 读取数据 Console.WriteLine(values); // 断开机床连接(耗时4-5秒) Environment.Exit(0); }
需要修改app1的代码,实现app2输出数据后立即读取,无需等待其退出。
解决方案
方法1:异步逐行读取标准输出
ReadToEnd()会一直阻塞直到进程关闭标准输出流(即进程退出),改用异步的ReadLineAsync()可以在app2输出数据后立即获取:
public async Task ReadValuesFromApp2Async() { Process_OPCDA = new Process { StartInfo = new ProcessStartInfo { FileName = MTX_OPC_DA_reader_path, Arguments = arguments, UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true } }; Process_OPCDA.Start(); // 异步读取输出的第一行(匹配app2仅输出一行数据的场景) string itemValues = await Process_OPCDA.StandardOutput.ReadLineAsync(); // 此处可直接使用itemValues,无需等待进程退出 // 若需处理多轮输出,可循环调用ReadLineAsync直到返回null // 可选:无需等待进程完成,但建议后续释放资源 // Process_OPCDA.WaitForExit(); Process_OPCDA.Dispose(); }
方法2:使用OutputDataReceived事件监听输出
通过注册事件回调,app2每输出一行数据就会立即触发处理逻辑:
private string _receivedValue; public void ReadValuesFromApp2() { Process_OPCDA = new Process { StartInfo = new ProcessStartInfo { FileName = MTX_OPC_DA_reader_path, Arguments = arguments, UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true } }; // 注册输出接收事件 Process_OPCDA.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { _receivedValue = e.Data; // 这里可即时处理数据,比如更新UI、触发业务逻辑等 } }; Process_OPCDA.Start(); // 启动异步监听输出 Process_OPCDA.BeginOutputReadLine(); // 无需WaitForExit,数据会在事件回调中即时获取 // 可后台等待进程退出后释放资源,避免内存泄漏 _ = Task.Run(() => { Process_OPCDA.WaitForExit(); Process_OPCDA.Dispose(); }); }
关键说明
- 原代码中
ReadToEnd()的阻塞特性是延迟获取数据的核心原因,它必须等待进程关闭输出流才能返回结果。 - 两种方案都能绕过进程退出的等待逻辑,在app2输出数据后立即完成读取。
- 务必注意在合适时机释放
Process资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Mdarende
相关产品推荐
相关产品推荐

