【问题标题】:Process.Start is blocking/hanging randomly on some clientsProcess.Start 在某些客户端上随机阻塞/挂起
【发布时间】:2011-08-07 19:45:42
【问题描述】:

(有一个非常相似的话题从未得到解决:here

我们有一个大型应用程序在多个客户端上运行,但最近我的一些代码停止工作。添加一些调试代码我发现代码在调用 Process.Start() 时停止(没有设置 shellexecute=true)。

调用很简单

 Process.Start(new ProcessStartInfo("program"))    

在 BackgroundWorker 线程中。

“程序”应用程序执行它应该执行的操作并退出。

我们的应用程序在线程处于后台时继续运行,但如果应用程序在 GUI 线程上运行另一个 Process.Start,则应用程序会锁定。如果应用程序通过 X 按钮关闭,应用程序仍会显示在任务管理器中,因为线程仍被 Process.Start 阻塞。

问题是这种行为无法重现。它在某些客户端计算机上随机发生。

会发生什么导致 Process.Start() 挂起? (Program.Main 用 [STAThread] 标记)

我目前刚刚做了一个解决方法,在它自己的线程中启动 Process.Start(),如果到那时它还没有返回,则在 5 秒后将其杀死。但这对于等待代码返回的用户来说是 5 秒(我不知道我可以将超时设置多低,因为在某些情况下我需要 Process.Start() 上的返回值)。

会不会有杀毒软件干扰? (客户端安装了 Symantec AV)

更新:我假设当我做了一个

ProcessStartInfo psi = new ProcessStartInfo("ping", "localhost");

默认情况下 psi.UseShellExecute 为 FALSE...这是不正确的。它默认为真。这正常吗?

【问题讨论】:

  • 要排除 AV,创建运行 sysinternals filemon 的进程,看看新进程的可执行文件是否有任何问题
  • 如何杀死线程?你为什么要杀死线程?你检查 Bgw.Completed 中的错误吗?
  • @Alex 如果程序重新启动,它会再次正常运行。所以很难重现,这意味着 filemon 可能运行得很好。
  • @Henk。杀死线程只是一种解决方法,因此应用程序继续按应有的方式运行。用 Process.Start() 调用的程序已经运行并完成了它的工作。尽管如此,.Net 代码仍然挂在那里,这是不应该的。所以我用 Abort 杀死线程。我不会杀死 BG 线程。我已将 Process.Start 移到一个新方法中,该方法创建一个线程并在没有返回时将其杀死。 Process.Start 正在阻塞线程。没有出现错误。
  • @Alex。我使用了 filemon,然后使用了 procmon。在程序运行之前我看不到任何访问程序的内容,但我不知道 procmon 是否会注意到底层 DLL 上的 misc 调用的系统挂钩。

标签: c# blocking process.start


【解决方案1】:

我知道这个帖子有点老了,但如果有人感兴趣,这是由外壳扩展(在这种情况下是防病毒软件)引起的。基本上,当您以 UseShellExecute=true(default) 启动时,防病毒软件会干扰 Processor.Start 并使其挂起(似乎是随机的)。有趣的是,进程启动得很好,挂起的是调用者线程。

在我们客户的一台服务器中启用了赛门铁克病毒防护时,我们遇到了同样的问题。我们通过在防病毒软件上设置例外来修复它。或者,您可以禁用 UseShellExecute。

【讨论】:

  • 应该是这个吧。对我来说,解决方法是在自己的线程中运行 Process.Start,如果它永远不会返回,则终止该线程。
  • 使用 UseShellExecute=false 我得到“访问被拒绝”异常。有了它=true,我得到了电话永远不会返回的问题。因此,如果我这样做,我会被诅咒,如果我不这样做,我会被诅咒。还有什么想法吗?
【解决方案2】:

前段时间我遇到了一个问题,如果其他东西在错误的时间读取程序输出,那么向外部进程发起攻击可能会导致竞争条件。这可能是你所看到的吗?

有关MSDN article on StandardOutput的更多信息。

edit:记忆慢慢恢复。我正在使用 process.ReadToEnd() after process.WaitforExit()。输出缓冲区非常小,因此有效地填满然后停止,等待某些东西(我,即进程调用者)读取它。它当然不能这样做,因为我的代码仍在等待进程完成。

Puting process.ReadToEnd() before WaitForExit() 为我修复了它,虽然这听起来很直观。但是,如果您不向控制台吐出详细的输出,那么它可能完全是另外一回事......

【讨论】:

  • 外部程序是一个 3d 方程序,可确保仅运行 1 个实例。也就是说,每当使用参数调用程序时,它都会被发送到程序的所有已运行实例并自行退出。它不是控制台程序,所以应该没有输出(?)。我不知道在进行单实例运行检查时使用了什么样的通信。 Process.Start 单独运行,而不是与另一个调用同时运行。更准确地说。在 BG 线程中调用此程序之前,在 GUI 线程上使用 .WaitForExit + Sleep(500ms) 完成对同一程序的调用。
猜你喜欢
  • 2012-08-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 2016-12-03
  • 2014-11-26
  • 1970-01-01
  • 2019-02-14
  • 2017-04-18
相关资源
最近更新 更多