Process.StandardOutput.ReadToEnd();中的DeadLock问题;

Gra*_*ton 7 c# deadlock process

读到这部分代码可能导致死锁:

 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();
Run Code Online (Sandbox Code Playgroud)

因为

如果父进程p.WaitForExit 之前调用p.StandardOutput.ReadToEnd并且子进程写入足够的文本来填充重定向的流,则可能导致死锁条件.父进程将无限期地等待子进程退出.子进程将无限期地等待父进程从完整的StandardOutput流中读取.

但我不是为什么.我的意思是,在这种情况下,父母的过程是什么,孩子是什么?

Fre*_*örk 12

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

应用程序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();
Run Code Online (Sandbox Code Playgroud)

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

  • 那么...我怎样才能运行一个进程,比如带有一些参数的“sqlcmd.exe”,时间不超过5分钟,并读取尽可能多的stdout和stderr?我找不到一种干净简单的方法来做到这一点。 (2认同)