【发布时间】:2014-08-31 19:13:00
【问题描述】:
我在使用 TCP 绑定的自托管应用程序中有一个 WCF 服务。如果我从应用程序启动外部进程“commandLineApp”,即使在我的应用程序关闭后仍会继续,那么下次我的应用程序启动 WCF 服务时会遇到问题。
WCF 表示地址/端口已在使用中。如果我在重新启动应用程序之前关闭外部应用程序(根本不使用 WCF 或任何套接字),WCF 服务就会正常启动。
看起来我的应用程序的套接字句柄以某种方式被新进程“commandLineApp”继承,并且在该进程退出之前不会被释放。
如何防止其他进程从我的主应用程序继承句柄(或成为子进程?)?目前我正在使用 Process.Start 启动另一个进程,使用 UseShellExecute 设置为 False,因为我需要同时设置 EnvironmentVarables 和 RedirectStandardOutput/Error。
如果我设置 UseShellExecute = true,我认为子进程设置会被阻止,但是我没有获得我需要的所有功能。
有没有办法解决这个问题?请参阅下面的示例代码。
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "commandLineApp.exe";
psi.Arguments = "/someParameter";
psi.EnvironmentVariables.Add("...", "...");
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
Process process = new Process();
process.StartInfo = psi;
process.Start();
// Monitor if process with PID = process.Id is running
// ...
编辑 - 附加信息: 执行“netstat -noa”表示端口被主应用程序的前一个 PID 以 LISTEN 状态使用,但不再有具有该 PID 的进程。一旦我关闭“commandLineApp”,netstat 命令就不再列出该端口。
WCF 服务在主应用退出前是这样关闭的:
try
{
serviceHost.Close(TimeSpan.FromSeconds(4));
}
catch (Exception)
{
serviceHost.Abort();
}
【问题讨论】:
-
您重定向标准 I/O 然后退出?我认为您的设计有些问题......另外请注意,如果双方都没有正常关闭,TCP 连接可以在它们“关闭”后存活几分钟。你确定“父母”真的死了吗?它不是有一些线程在运行吗?你是如何处理关机的?无论如何,您应该明确关闭所有句柄,因此您的关闭听起来不是很优雅......总而言之,您不应该依赖进程退出清理之后 - 您应该自己进行清理!
-
我敢打赌这与继承的句柄无关,而与不使用
SO_REUSEADDR引起的延迟有关 -
嗨,我等了几个小时,我已经验证了主进程已经终止。执行“netstat -noa”表示该端口被主应用程序的前一个 PID 使用,但不再有具有该 PID 的进程。我手动清理了所有 WCF 服务,关闭时没有留下任何线程。如果我不启动“commandLineApp”,我在重新启动主应用程序时根本没有任何问题,因此它与该过程的启动方式非常相关。 I/O的redirect是从“commandLineApp”获取第一分钟的输出,发现启动问题。
-
@Dark Falcon - 你知道 SO_REUSEADDR 是否可以与 WCF 结合使用吗? WCF 通常会隐藏所有低级套接字选项。
标签: c# .net wcf sockets process