从Process.Start()调用时,C#应用程序随机挂起

use*_*135 5 .net c# windows-services windows-server-2012

我已设置Windows服务来管理自定义.Net任务。组织为:

-Windows Service监视计划,并根据需要启动工作程序.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.
Run Code Online (Sandbox Code Playgroud)

那时,工作程序可执行文件启动-在任务管理器中它看起来通常是正常的。唯一提示我出问题的地方是内存消耗-在正常情况下,工作进程在启动期间会达到5MB左右,并且会增长以反映任务,但是当进程冻结时,它只会达到2MB左右并停止。

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

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


我将其安装在服务可以自动检测并适当处理的位置,因此这不是紧迫的问题,但是如果原因或解决方案对任何人都很突出,我仍然想解决此问题。


worker的初始化代码只是一个标准的win窗体启动程序,我的东西开始在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.
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据注释,将服务设置为在看到挂起的进程时使用它创建的日志条目记录一个小型转储。明天将检查它,看看会带来什么。


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

小型转储显示代码在静态void main的退出}处停止/卡住,即:

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

否则一切似乎都很好。

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


编辑2015年9月4日#2:调整了工作程序的启动状态,似乎工作正常。其要旨是删除Form引用,仅使用应用程序上下文(例如codeproject示例

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

现在的代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

use*_*135 1

根据最后一点,将表格部分从其中全部拉出来似乎已经解决了问题。此时,我假设 server 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.
Run Code Online (Sandbox Code Playgroud)

工人:

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
    }
}
Run Code Online (Sandbox Code Playgroud)