处理来自子进程的交互式提示

时间:2012-06-25 14:46:25

标签: .net process stream synchronization deadlock

我正在扩展一个.NET4命令行应用程序,除其他外,它创建一个外部进程来调用svn.exe从我们的存储库中提取一些数据。问题是当我们的帐户密码更改时,身份验证失败,SVN会提示输入帐户密码。

SVN通过向标准错误写提示来完成此操作。输出如下:

STDOUT: Updating '.':
STDERR: Authentication realm: <http://{host}:8080> VisualSVN Server
STDERR: Password for 'joe.smith':

我认为它出错的地方是来自子进程的第二个“行”(以后的CP)不包含换行符,并且可能没有被 BeginErrorRead 拾取(在父进程(PP)阻塞标准输入流之前。关闭CP上的输入流会导致输出和错误流中的剩余数据由我的 DataReceivedEventHandler 回调处理。

支持我的猜测。

事件序列似乎是:

  1. CP开始写入STDOUT。
  2. 如果缓存的身份验证凭据错误,CP会开始将上述消息写入STDERR。
  3. 根据我是否从STDERR同步或异步读取,会发生以下情况:
    • 同步:当等待来自STDERR的更多数据时,CP似乎等待来自STDIN的输入。即使偷看或检查流是否关闭也会导致死锁。
    • 异步:在CP等待从STDIN读取之前,未读取第二行。
  4. 假设我已正确诊断出问题,我仍然不知道如何应对。

    至于我尝试的选项:

    • 关注this MSDN article,我试图同步读取标准错误。这似乎充满了危险,因为任何方法一读到标准错误的最后一个字符就会无限期地阻塞。
    • 上一个链接也建议“或者,您可以通过创建两个线程并在单独的线程上读取每个流的输出来避免死锁条件。”,但是我在这条轨道上的努力显然是明显的非常误导。我不知道线程如何帮助,当我知道我已经到达流的末尾时,为时已晚。

    为了澄清,如何在不造成死锁的情况下安全地读取到标准错误流的末尾?

1 个答案:

答案 0 :(得分:1)

我认为您的分析是正确的。我不得不做一些CP stdio重定向,在Win32上总是很痛苦(设计为UI平台而不是命令行......)。

无论如何,您可以尝试从实际流中读取(使用BeginReadReadAsync,如果是.NET 4.5)并自行进行Encoding转换。那将是我的第一次尝试。

否则,您必须使用多个线程。我以前做过这件事,这很痛苦。

无论哪种方式,你实际上并没有等待CP的stderr结束。只需监控它为你的魔法字符串。大多数控制台程序在退出之前不会关闭它们的stdout或stderr,因此在它退出之前你无法一直读到它。