Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是什么破坏了我的进程。StartInfo.OutputDataReceived回调过早?_C#_Multithreading_Process_Stdout_Stderr - Fatal编程技术网

C# 是什么破坏了我的进程。StartInfo.OutputDataReceived回调过早?

C# 是什么破坏了我的进程。StartInfo.OutputDataReceived回调过早?,c#,multithreading,process,stdout,stderr,C#,Multithreading,Process,Stdout,Stderr,以下问题发生在.NET Framework v3.5上。不知道它是否适用于v4* 为了捕获某些进程的标准输出,我成功地使用了p.StartInfo.UseShellExecute=false和p.StartInfo.RedirectStandardOutput=true和连接到p.StartInfo.OutputDataReceived+=…;的事件处理程序。然后我调用p.Start()然后p.BeginOutputReadLine()然后p.WaitForExit() 到目前为止一切顺利。正如

以下问题发生在.NET Framework v3.5上。不知道它是否适用于v4*

为了捕获某些进程的标准输出,我成功地使用了
p.StartInfo.UseShellExecute=false
p.StartInfo.RedirectStandardOutput=true和连接到
p.StartInfo.OutputDataReceived+=…;的事件处理程序。然后我调用
p.Start()然后
p.BeginOutputReadLine()然后
p.WaitForExit()

到目前为止一切顺利。正如预期的那样,我在事件处理程序中逐行获取所有标准输出

我必须引入一个超时,而不是
WaitForExit()
,因为一些进程不可预测地在stdin触发输入请求(例如,你确定吗?[y/n]),导致死锁,我会永远等待,他们也会这样做

我尝试的第一件事是在(!p.HasExited&&DateTime.Now其中
timeoutmoment
proc.Start()
后2分钟。这就是我遇到问题的时候。非常一致的是,该代码适用于最多生成几百行stdout的调用,但对于一个生成大约7500行stdout的调用,它会中断。发生的是
proc.WaitForExit(200)线程退出
,而
当我的
OutputDataReceived
事件处理程序只被调用了约7300行时(这个数字同样非常一致,在测试之间只变化了+/-1),其余的stdout行不再调用处理程序,因此我丢失了它们

奇怪的是,如果我避免使用
WaitForExit(200)
而在(!p.HasExited&&DateTime.Now,问题就不会出现(以下代码中未显示)。当我发布这个问题时,我非常确定使用
Sleep(1000)
可以避免这个问题,但我错了。它像那样工作了几十次,然后就没有了,它开始表现得就像我选中
WaitForExit(200)
时一样

我现在推测这个问题的原因是(1)我处理每个
OutputDataReceived
回调的时间太长。我注意到,当我在事件处理程序中添加一个条件断点时,问题变得更加严重,这大大延长了方法的执行时间。我现在可以通过简单地添加3x Debug.writeline而不使用条件断点来重现问题;另外(2)在系统有机会对我的事件处理程序执行所有回调之前,我访问
haseexit
/
WaitForExit(200)
,不知何故,我的上下文被破坏了。现在,我在
p.Start()
之后和访问任何
p.*
方法之前,执行一个盲
System.Threading.Thread.Sleep(30000)
,并获得所有回调。当我使用
WaitForExit()
时,似乎我可以花多少时间来处理每个回调,但我仍然可以得到所有回调

有人能更明白这一点吗

代码:

private int\u execOsProc(
ProcessStartInfo Psi
,字符串SecInsensArgs
,TextWriter ExtraStdOutAndErrTgt
,布尔输出ExtrastAutoly
)
{
var pr=新流程();
pr.StartInfo=Psi;
pr.StartInfo.UseShellExecute=false;
pr.StartInfo.RedirectStandardOutput=pr.StartInfo.RedirectStandardError=true;
pr.StartInfo.CreateNoWindow=true;
var ol=新数据接收到的数据处理器(此.\u stdOutDataReceived);
var el=新数据接收到的数据处理程序(此.\u stdErrDataReceived);
pr.OutputDataReceived+=ol;
pr.ErrorDataReceived+=el;
尝试
{
__logger.Debug(“正在执行:\”“+pr.StartInfo.FileName+”\”“+secinsargs);
如果(ExtraStdOutAndErrTgt==null)
{
这是.uu outputoExtrastAutoly=false;
}
其他的
{
这是.\uu extraStdOutAndErrTgt=extraStdOutAndErrTgt;
这是.uu outputExtrastAutoly=outputExtrastAutoly;
}
pr.Start();
pr.BeginOutputReadLine();
pr.BeginErrorReadLine();
var startmom=DateTime.Now;
var timeoutmom=startmom.AddMinutes(2);
而(!pr.hasExit&&DateTime.Nowvar startmom = DateTime.Now;
var timeoutmom = startmom.AddMinutes(2);
while (!pr.HasExited && DateTime.Now < timeoutmom)
    pr.WaitForExit(200);

if (pr.HasExited)
{
    WaitForExit();//Ensure that redirected output buffers are flushed

    pr.CancelOutputRead();
    pr.CancelErrorRead();

    __logger.Debug("Execution finished with exit status code: " + pr.ExitCode);
    return pr.ExitCode;
}
else
{
    pr.CancelOutputRead();
    pr.CancelErrorRead();

    __logger.Debug("Timeout while waiting for execution to finish");

    pr.Kill();
    return -100;
}