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

调用StandardOutput.ReadToEndAsync时代码最后一行挂起是什么原因?

挂起问题成因

  • 核心原因是你启动的cmd.exe执行完curl命令后不会主动退出,会持续等待新的输入指令,StandardOutput.ReadToEndAsync()需要等待进程输出流完全关闭才会返回,进程不退出、输出流不结束,自然就会永久挂起。
  • 另一个潜在死锁诱因:你只读取了标准输出流,没有处理标准错误流,如果进程往标准错误写了较多内容,缓冲区被占满后操作系统会强制挂起进程,等待缓冲区被读取,也会导致程序无响应。

基于异步的优雅解决方案

如果不需要用cmd执行多条命令,推荐直接启动目标进程,不要套一层cmd,实现更简洁:

var process = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = "curl",
        Arguments = "http://example.com",
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true
    }
};
process.Start();

// 同时异步读取两个输出流,避免缓冲区满导致死锁
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();

// 等待进程退出和两个读取任务全部完成
await Task.WhenAll(process.WaitForExitAsync(), outputTask, errorTask);

// 拿到最终结果
var response = outputTask.Result;
var errorInfo = errorTask.Result;

如果确实需要依赖cmd执行多条命令,主动关闭标准输入通知cmd没有后续指令即可:

var process = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = "cmd.exe",
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true
    }
};
process.Start();

// 写入需要执行的所有命令
await process.StandardInput.WriteLineAsync("curl http://example.com");
// 关键:关闭标准输入,cmd收到信号后执行完命令就会自动退出
process.StandardInput.Close();

var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
await Task.WhenAll(process.WaitForExitAsync(), outputTask, errorTask);

var response = outputTask.Result;

注:WaitForExitAsync是.NET 5及以上版本自带的原生异步API,如果使用低于.NET 5的版本,只需对进程退出事件做简单的异步封装即可,不需要使用老旧的Begin/End模式。

内容的提问来源于stack exchange,提问作者JohnWick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 16:54:03