如何实现Go与C#控制台程序的长期管道连接
Go与C#进程间多次管道交互问题排查与修复
问题分析
你的代码存在两个关键问题导致无法实现多次交互:
- Go端:
io.WriteString(stdin, w1)未添加换行符,而C#的Console.ReadLine()需要读取到换行才会返回;同时io.ReadAll(stdout)会持续读取直到进程退出(EOF),第一次读取后会阻塞后续操作。 - 调试符号错误:大概率是C#程序未生成调试符号(pdb文件),或附加进程时未选择正确的调试模式。
修复方案
1. 修正Go程序代码
调整输入输出逻辑,确保每行输入带换行,同时用逐行读取替代ReadAll:
package main import ( "bufio" "fmt" "log" "os/exec" ) func main() { cmd := exec.Command("path/to/ConsoleApp.exe") // 替换为实际路径 stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } if err := cmd.Start(); err != nil { log.Fatal(err) } defer cmd.Wait() // 确保进程退出时等待 // 创建stdout的逐行读取器 scanner := bufio.NewScanner(stdout) for { var w1 string _, err := fmt.Scanln(&w1) if err != nil { log.Fatal(err) } // 写入输入并添加换行符,匹配Console.ReadLine的要求 _, err = fmt.Fprintf(stdin, "%s\n", w1) if err != nil { log.Fatal(err) } // 读取C#程序输出的一行结果 if scanner.Scan() { fmt.Println("当前累加结果:", scanner.Text()) } if err := scanner.Err(); err != nil { log.Fatal(err) } } }
2. 优化C#程序调试与逻辑
- 调试符号问题:确保C#项目设置为Debug模式,在生成选项中勾选"生成调试信息"(默认Debug模式已开启),编译后会生成和exe同名的pdb文件,附加进程时选择该exe即可正常调试。
- 优化文件标记逻辑并增加控制台调试输出:
using System; using System.IO; namespace ConsoleApp { class Program { static int Main(string[] args) { double sum = 0; bool flag = true; while (flag) { var str = Console.ReadLine(); // 直接输出接收内容到控制台,方便调试 Console.WriteLine($"收到输入:{str ?? "空内容"}"); double addend; flag = double.TryParse(str, out addend); using (StreamWriter writer = new StreamWriter("t.txt", append: true)) // 改为追加模式,避免覆盖历史记录 { writer.WriteLine($"[{DateTime.Now}] 收到:{str},转换成功:{flag}"); } sum += flag ? addend : 0; Console.WriteLine(sum); } return 0; } } }
关键修复点说明
- Go端必须添加换行符:
Console.ReadLine()以换行作为输入结束标志,没有换行的话C#进程会一直等待输入。 - 替换
io.ReadAll为bufio.Scanner:ReadAll会等待进程输出EOF才返回,而我们需要的是每次交互后的单行结果,逐行读取更符合需求。 - 移除不必要的goroutine:写入stdin不需要异步,同步写入能确保输入发送完成后再读取结果,避免时序问题。
内容的提问来源于stack exchange,提问作者dragondangun
相关产品推荐
相关产品推荐

