为何C#控制台应用启动Process后卡顿、Console.ReadLine响应延迟?
问题根源
你这段进程启动代码有三个逻辑错误,直接导致控制台IO被阻塞,出现你说的1分钟左右卡顿:
- 异步读取启动后立刻调用
appProcess.Dispose():BeginOutputReadLine和BeginErrorReadLine都是基于线程池的异步IO操作,你刚启动读取就释放进程对象,会导致底层管道句柄处于半销毁状态,运行时需要等待未完成的异步IO操作超时(默认超时刚好约60秒)才能完成资源回收,这段时间会锁住控制台输入输出流。 - 缺少必要的进程启动配置:重定向标准流必须显式设置
UseShellExecute = false,同时要设置CreateNoWindow = true,否则ADB进程会默认附加到当前程序的控制台,和主程序争抢控制台输入流的所有权。 - 未处理进程退出和句柄继承问题:ADB是C/S架构,执行启动App的命令时客户端进程会快速退出,但如果没有主动关闭不需要的流句柄,后台启动的ADB Server进程会继承当前控制台的输入句柄,直到系统超时回收继承句柄前,主程序的
Console.ReadLine()都拿不到输入流控制权。
修复代码
直接替换原有ADB启动段即可:
// --- Start an app with ADB: var appProcess = new Process(); var appInfo = new ProcessStartInfo(); appInfo.FileName = ADB_PATH; appInfo.Arguments = ... ; // 保留你原来的启动参数 // 核心配置项,缺一不可 appInfo.RedirectStandardError = true; appInfo.RedirectStandardOutput = true; appInfo.RedirectStandardInput = true; appInfo.UseShellExecute = false; appInfo.CreateNoWindow = true; appProcess.StartInfo = appInfo; // 先注册流事件再启动进程,避免丢失启动初期的输出 appProcess.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { if (e.Data == null) return; // 过滤流结束的空标记 // 你的原有输出处理逻辑 }; appProcess.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { if (e.Data == null) return; // 你的原有错误处理逻辑 }; appProcess.Start(); appProcess.BeginErrorReadLine(); appProcess.BeginOutputReadLine(); // 主动关闭不需要的标准输入流,避免句柄被ADB后台进程继承 appProcess.StandardInput.Close(); // 等待ADB客户端进程执行退出,启动App的命令最多等5秒足够 appProcess.WaitForExit(5000); // 等进程退出、异步读取完成后再释放资源,绝对不能提前Dispose appProcess.Dispose(); // ----------------------------
注意事项
- 如果你的ADB参数带了
wait-for-device这类阻塞逻辑,把WaitForExit的超时时间调到对应合理值即可,不要无限等待。 - 流接收事件是在后台线程触发的,不要在事件处理函数里直接调用
Console类的方法写控制台,跨线程调用控制台IO不加锁会导致偶发卡死,需要打日志的话要么加锁,要么把日志内容投递到主线程队列统一输出。 - 如果你不需要实时获取ADB的输出日志,直接把
RedirectStandardOutput和RedirectStandardError设为false即可,去掉流重定向逻辑后性能更好,也不会出现句柄争抢问题。
内容的提问来源于stack exchange,提问作者massivemoisture
相关产品推荐
相关产品推荐

