【问题标题】:C# app hangs randomly when called from Process.Start()从 Process.Start() 调用时,C# 应用程序随机挂起
【发布时间】:2015-09-03 19:46:50
【问题描述】:

我设置了一个 Windows 服务来管理自定义 .Net 任务。组织是:

-Windows 服务监控计划并根据需要启动工作程序 .exe。

-Worker .exe(轻量级 Winform 应用程序)使用命令行参数拉出 DLL(插件)并运行一些代码。

这几个月来一直运行良好。我最近将它迁移到 Server 2012(从 2008 IIRC)——这可能无关,但很难说。迁移后一段时间以来,我遇到了一个问题,即 worker .exe 在被 process.start() 调用后“启动”,但没有到达我的代码。没有错误或任何东西,它似乎只是在应用加载期间冻结。

启动它的服务代码相当标准。

// Create a temp folder and copy the executable to it
// (so the source exe isn't always in use and can be swapped out)

Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = Path.Combine(temp.Path, Path.GetFileName(ExecutablePath));
psi.Arguments = CommandLineArgs.ConcatenateList(" ");
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = psi;
p.Start();

// read standard output if necessary, kill and reschedule if appears to be frozen, etc.

此时,worker 可执行文件启动 - 它在任务管理器中看起来很正常。唯一让我知道出现问题的是内存消耗 - 在正常情况下,工作人员在启动期间会达到 5MB 左右并增长以反映任务,但当进程冻结时,它只会达到 2MB 左右并停止。

为了证明它不是我在工作程序中的任何代码,我在第一行添加了对日志记录函数的调用,但从未见过日志。

没有错误消息,而且 - 真正奇怪的一点 - 这不是一个一致的问题。现在冻结的完全相同的呼叫将在 30 秒后正常运行。问题发生时似乎也没有任何真正的模式 - 我看到的最接近的事情是它偶尔会同时发生在多个任务上(例如,它可能会影响在问题发生时开始的所有任务发生在任何任务中)。


我有它,服务可以自动检测它并适当地处理它,所以这不是一个紧急问题,但如果一个原因或解决方案对任何人来说都很突出,我仍然想解决这个问题。


worker 的初始化代码只是一个标准的 win forms 启动,我的东西开始在 form_load 中被调用。

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    // Do Stuff - never gets hit when the freeze happens.
}

编辑:每个 cmets,设置服务以使用它在看到挂起进程时创建的日志条目记录小型转储。明天会检查它,看看它会发生什么。


2015 年 9 月 4 日编辑:小型转储信息:

minidump 显示代码在 static void main 的退出 } 处停止/卡住,即:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
} // <------ This is where the main thread is frozen.

否则一切似乎都很好。

我将做一些研究并尝试对工人进行一些更改以防万一。


编辑 2015 年 9 月 4 日 #2: 调整了工人启动,它似乎正在工作。它的要点是删除表单引用并仅使用应用程序上下文(例如codeproject sample)

我用任务请求敲打了系统,它没有任何问题。我会让它在周末运行作为测试,并在周二进行状态更新。 仍然很好奇为什么它会随着表单加载而随机中断。

现在的代码:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.Run(new AppContext());
    }
}

class AppContext : ApplicationContext
{
    public AppContext()
    {
        // Do Stuff
    }
}

【问题讨论】:

  • 我认为您应该发布该工作程序 .exe 的初始化代码。
  • 已更新 - 在 form_load 之前,它只是标准的(VS 生成的)init 东西,此时我的东西(通常)会启动。将日志调用作为 form_load 的第一行是我想出来的没有达到那个点。
  • 您是否尝试过在进程挂起时将其转储并加载到 VS/WinDBG 以找出它挂起的位置?
  • 您是否尝试过独立运行该 WinForms 程序以查看它是否启动?我认为您的表单定义本身有问题,导致无法对其进行初始化。
  • 还没有——我通常不需要进行远程调试,所以我不太确定所有可用的工具。编辑因为 shift+enter vs enter:我将对服务进行一些调整,下次发生时试一试。

标签: c# .net windows-services windows-server-2012


【解决方案1】:

我还不能对你的帖子添加评论(我会因为这样做而被其他 stackoverflow 用户销毁,但是......)

我遇到了一个和你很相似的问题。我的问题来自启动服务的会话。在迁移期间,该服务在新操作系统中的“会话 0”中启动,而不是作为“系统”程序。它是在我们的程序许可下发布的,可以通过服务运行。 也许你应该检查这一点。

对不起,如果我把它作为答案而不是在评论中告诉它

【讨论】:

  • 没问题,我理解痛苦(现在只有 11 个代表)。 Grrr,再次编辑,因为 enter vs shift+enter:在这种情况下,服务在相应会话中使用超级管理员凭据运行。
  • 您是否从您的服务获得此信息?即使是微软也无法解决我们的问题……我们绝望地尝试了多种方法后才发现。以防万一,请仔细检查。至少,你会确定:P
【解决方案2】:

最后一点,将表单部分从其中拉出来似乎已经解决了这个问题。在这一点上,我假设服务器 2012 不喜欢 winform 应用程序在某些情况下不显示的情况;因为它大部分时间都在工作,并且表单的代码没有任何变化。

服务:

// Create a temp folder and copy the executable to it
// (so the source exe isn't always in use and can be swapped out)

Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = Path.Combine(temp.Path, Path.GetFileName(ExecutablePath));
psi.Arguments = CommandLineArgs.ConcatenateList(" ");
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = psi;
p.Start();

// read standard output if necessary, kill and reschedule if appears to be frozen, etc.

工人:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.Run(new AppContext());
    }
}

class AppContext : ApplicationContext
{
    public AppContext()
    {
        // Do Stuff
    }
}

【讨论】:

    猜你喜欢
    • 2017-06-17
    • 1970-01-01
    • 2013-05-23
    • 2022-11-11
    • 2012-08-15
    • 2014-01-14
    • 2019-11-24
    • 2012-09-12
    • 2015-04-11
    相关资源
    最近更新 更多