【问题标题】:DeadLock Issues in Process.StandardOutput.ReadToEnd();Process.StandardOutput.ReadToEnd() 中的死锁问题;
【发布时间】:2009-09-25 16:15:27
【问题描述】:

read这部分代码可能会导致死锁:

 Process p = new Process();

 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "Write500Lines.exe";
 p.Start();
 p.WaitForExit();
 string output = p.StandardOutput.ReadToEnd();

因为

如果发生死锁情况,可能会导致 父进程调用p.WaitForExitp.StandardOutput.ReadToEnd 之前和 子进程写入足够的文本 填充重定向的流。这 父进程将无限期等待 让子进程退出。这 子进程将无限期等待 让家长阅读全文 标准输出流。

但我不太明白为什么。我的意思是,在这种情况下,父进程是什么,子进程是什么?

【问题讨论】:

    标签: c# process deadlock


    【解决方案1】:

    简而言之,这就是可能发生的情况:

    应用程序 A(您上面的代码)启动子进程 B 并重定向标准输出。然后A等待B进程退出。当 A 等待 B 退出时,B 将输出生成到输出流(A 已重定向)。此流具有有限的缓冲区大小。如果缓冲区已满,则需要将其清空以便 B 能够继续写入。由于 A 在 B 退出之前不会读取,因此您最终可能会遇到 B 将等待输出缓冲区清空,而 A 将等待 B 退出的情况。两者都在等待对方采取行动,而您陷入了僵局。

    您可以尝试以下代码来演示问题:

    ProcessStartInfo psi = new ProcessStartInfo();
    psi.FileName = "cmd";
    psi.Arguments = @"/c dir C:\windows /s";
    psi.RedirectStandardOutput = true;
    psi.UseShellExecute = false;
    Process p = Process.Start(psi);
    p.WaitForExit();
    string output = p.StandardOutput.ReadToEnd();
    

    这将(很可能)产生输出流已满的情况,以便子进程(在这种情况下为"cmd")将等待它被清除,而上面的代码将等待cmd完成。

    【讨论】:

    • 感谢您的清晰解释。
    • 那么......我怎样才能运行诸如sqlcmd.exe 之类的带有一些参数的进程不超过5 分钟,并尽可能多地读取stdout 和stderr?我找不到一个干净简单的方法来做到这一点。
    【解决方案2】:

    父进程调用p.Start()。我猜这是你的应用程序(调用者)。 子进程是p,也就是被调用者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-28
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多