首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >消除Process.WaitForExit() / StandardOutput死锁条件

消除Process.WaitForExit() / StandardOutput死锁条件
EN

Stack Overflow用户
提问于 2016-09-04 02:05:59
回答 1查看 1.3K关注 0票数 1

我已经读到过这个死锁条件,我很确定它正在影响我的代码(如下所示)。我不明白的是:在过去的12年中,这段代码在WindowsServer2003Windows2.0 (.net 2.0)上运行得非常好。现在,我们一直在尝试将其移到Windows 2012,在那里,它总是处于死锁状态。

虽然我的DLL是为"anyCPU“(仍然针对.net 2.0)构建的,但正在运行的可执行进程绝对是32位的,从Server 2003到Server 2012的迁移从32位到64位操作系统。

我想我理解如何解决这个问题,但是有人知道为什么这种行为会从Server 2003变成Server 2012吗?

代码语言:javascript
运行
复制
public string DoMyProcess(string filenameAndPath, string arguments)
{
    string stdout="";
    int exitCode = 0;               

    try 
    {               
        ProcessStartInfo procStartInfo = new ProcessStartInfo();
        procStartInfo.FileName = filenameAndPath;
        procStartInfo.CreateNoWindow = true;
        procStartInfo.Arguments = arguments;            
        procStartInfo.RedirectStandardOutput = true;
        procStartInfo.UseShellExecute = false;

        System.Diagnostics.Process theProcess = null;
        try
        {
            theProcess = Process.Start(procStartInfo);
            theProcess.WaitForExit();

            exitCode = theProcess.ExitCode;

            // moving this ABOVE WaitForExit should eliminate deadlocks
            // But why did it always work on Server 2003 but not on Server 2012?
            stdout = theProcess.StandardOutput.ReadToEnd();

        }
        catch (System.Exception e)
        {
            string errMsg = e.Message;
            log_the_error("threw an exception: " + e.Message);
        }                   
    }           

    return stdout;
}

更新:

即使在按照建议更改上述代码之后,仍然存在神秘死锁:

代码语言:javascript
运行
复制
        try
        {
            theProcess = Process.Start(procStartInfo);
            stdout = theProcess.StandardOutput.ReadToEnd();                     
        }
        catch (System.Exception e)
        {
            string errMsg = e.Message;
            log_the_error("threw an exception: " + e.Message);
        }                   
    }           

还有什么其他条件会导致这种僵局?如果我要检查StandardError,它会揭示什么有用的东西吗?

更新2:

FWIW,我们提供了另一个Windows Server 2003 (32位),它运行IIS 6。这是最初的机器配置,这段代码运行了12年(只有偶尔的死锁)。我们在Server 2012 IIS 8上的死锁代码在此服务器2003上不会死锁。

我们现在有了自己的最小和完整的代码来再现这个问题。但是,我们所授权的由流程执行的.exe具有保密条款,这些条款阻止我们发布。我知道这对这里的专家没什么帮助。

我们遇到的一个提示是,通过安装在实际服务器上的Visual 2013调试器运行时,进程不会死锁/挂起,而会从服务器外部的浏览器调用进程。奇怪的是--从2012年服务器上的浏览器,我们无法连接到那个测试页面--浏览器只是说“连接”,最终超时(但是,同一服务器/同一个IIS 8承载的其他站点可以从服务器上的浏览器到达!)

由于从管理命令shell或非管理命令shell手动运行相同的命令行参数,很难相信这是这个32位可执行文件的64位/ WOW64问题,或者它是必需的DLL。我们继续搜索权限可能会导致问题的位置(进程需要写入临时文件夹,目前我们已将该文件夹放在c:\temp )。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-04 02:16:32

如果没有一个好的最小、完整和可验证的代码示例,就不可能完全回答。

我可以告诉您的是,您的代码总是被破坏,并且始终存在死锁的可能性。在进程退出之前,您无法读取进程中的任何内容,但如果进程向stdout写入大量数据,以致缓冲区填充和阻塞进程,则进程可能无法退出。

如果您还没有重新编译任何东西,但是发现您以前没有看到过死锁,那么最有可能的解释是,您要开始的进程比以前更多地写入stdout。也就是说,以前所有的输出都适合缓冲区,但现在没有了。(我想在新操作系统中也有可能缩小缓冲区大小,但这对我来说似乎不太可能。)

您应该继续将电话转到ReadToEnd()。实际上,您应该完全取消WaitForExit()。如果您正在调用ReadToEnd(),在进程实际上已经退出之前,这是不可能完成的,因此事后调用WaitForExit()是没有意义的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39312934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档