C#创建Process调用外部程序卡死的原因分析和解决方案.pdfVIP

  • 15
  • 0
  • 约2.98千字
  • 约 2页
  • 2024-03-20 发布于上海
  • 举报

C#创建Process调用外部程序卡死的原因分析和解决方案.pdf

C#创建Process调⽤外部程序卡死的原因分析和解决⽅案

最近做项⽬发现创建Prcess调⽤外部程序时,当处理的数据量变⼤后,Prcess⽆法退出,主程序卡死。

原代码:

Using(Processprocess=newProcess())

{

process.StartInfo=newProcessStartInfo(executablePathargs);

if(workingFolder!=null)

{

process.StartInfo.WorkingDirectory=workingFolder;

}

process.StartInfo.CreateNoWindow=true;

process.StartInfo.UseShellExecute=false;

process.StartInfo.RedirectStandardOutput=true;

process.StartInfo.RedirectStandardError=true;

DateTimestart=DateTime.Now;

process.Start();

process.WaitForExit();

DateTimefinish=DateTime.Now;

stringprocessOutput=process.StandardError.ReadToEnd()+

process.StandardOutput.ReadToEnd();

}

这段代码的作⽤是调⽤⼀个外部程序向⼀个服务器上传⼀串数据,原来数据⼤⼩是128bit,现在是4Kbit。

尝试了各种⽅式,在⽹上搜集各类资料,查找可能卡顿的地⽅,本来以为是调⽤的外部程序的问题,最后发现是主程序的问题。

原因分析:

1.使⽤同步⽅式读取执⾏结,在StandardOutput.ReadTEnd之前调⽤了WaitfrExit,导致死锁。

原代码使⽤了同步读取执⾏结的⽅式,在StandardOutput.ReadTEnd之前调⽤了WaitfrExit。当调⽤⽅从⼦进程的重定向流中进⾏

读取时,它依赖于⼦进程。调⽤⽅等待读取操作,直到⼦级写⼊流或关闭流为⽌。当⼦进程写⼊⾜够的数据以填充其重定向流时,它依赖

于⽗进程。⼦进程将在下⼀次写⼊操作之前等待,直到⽗进程从整个流中读取或关闭流为⽌。当调⽤⽅和⼦进程等待彼此完成操作时,会

发⽣死锁条件,并且这两个情况都⽆法继续。

简单点说就是当数据量较⼤时,⼦进程写⼊的数据占满了重定向流,此时⼦进程会停⽌写⼊,等待⽗进程从流读取数据,然⽽⽗进程会等待

直到⼦进程完成写⼊流,此时⽗进程⼦进程相互等待,程序陷⼊死锁。

正确的⽅法应该是在WaitFrExit之前调⽤StandardOutput.ReadTEnd。

原代码⽗进程在调⽤StandardOutput.ReadTEnd之前调⽤WaitfrExit,并且⼦进程写⼊⾜够多的⽂本以填充重定向的流,则会导致死

锁情况。⽗进程会⽆限期地等待⼦进程退出。⼦进程会⽆限期地等待⽗进程从整个流中读取StandardOutput。

2.同时调⽤StandardErrr.ReadTEnd和StandardOutput.ReadTEnd.

和上⾯的原因同理,如⽗进程调⽤StandardOutput.ReadTEnd后跟StandardErrr.ReadTEnd,并且⼦进程写⼊⾜够的⽂本来填

充其错误流,则会导致死锁情况。⽗进程会⽆限期地等待⼦进程关闭其StandardOutput流。⼦进程会⽆限期地等待⽗进程从整个流中读

取StandardErrr。

解决⽅案:

使⽤异步⽅式读取执⾏结和错误信息,同时加⼊延时检查。

⽰例代码为异步读取数据的⽅法:

using(Processprocess=newProcess())

{

StringBuilderprocessOutputBuilder=newStringBuilder();

process.StartInfo=newProcessStartInfo(executablePathargs);

if(workingFolder!=nu

文档评论(0)

1亿VIP精品文档

相关文档