You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 20:21:02