【问题标题】:C# Windows Service: The service did not respond to the startC# Windows 服务:服务没有响应启动
【发布时间】:2011-07-20 19:34:03
【问题描述】:

这是我第一次尝试创建调用多个线程的 Windows 服务。我所做的是创建一个控制台应用程序,然后添加一个 Windows 服务和安装程序。我的代码如下。

partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        System.Timers.Timer timer1 = new System.Timers.Timer();
        timer1.Interval = 10000;
        timer1.Start();
        timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
    }

    public static void timer1_Elapsed(object sender, EventArgs e)
    {
        Program.ThreadController();   
    }

    protected override void OnStop()
    {
        // TODO: Add code here to perform any tear-down necessary to stop your service.
    }
}

class Program
{
    static void Main(string[] args)
    {
        ThreadController();
    }

    public static void ThreadController()
    {
        for (int i = 0; i < 3; i++)
        {
            new Thread(() => { processEventLogTesting(); });
        }
    }

    public static void processEventLogTesting()
    {
        EventLog.WriteEntry("ProcessThread1", "Process1 Works");
    }
}

我不确定为什么会收到此错误,任何提示都会很棒。

谢谢。

【问题讨论】:

    标签: c# multithreading windows-services


    【解决方案1】:

    processEventLogTesting () 中有无限递归。这就是它没有响应的原因。当我编写带有计时器的 Windows 服务时,我所做的只是连接回调并在 OnStart 中启动计时器。然后我坐下来让它做它的事情。您在启动时尝试做太多事情。

    【讨论】:

    • 好的,我把它拿出来了,还是不行,但是你有什么建议解决这个问题
    • 我真的不认为这是问题所在,错误停止发生在 timer.Start() 上
    • 它很可能会停在那里,但你在processEventLogTesting () 中有无限递归。 timer.Start () 可能正是 Windows 放弃该服务的地方。请参阅下面我的其他答案,了解您应该如何执行此操作。
    【解决方案2】:

    首先我会添加一些功能来进行调试。这实际上很容易(当您知道如何操作时!!!)。

    将此添加到您的课程中:

    [DllImport("kernel32.dll")]
    public static extern Int32 AllocConsole();
    

    然后将其添加到您的 main 函数中(如果您启用服务访问用户界面,那么在作为服务运行时您也可以这样做)。

    for (int loop = 0; loop < args.Count; loop++)
    {
      if (args[loop] == "debug")
        AllocConsole();
    }
    

    这为您提供了一个控制台窗口,您现在可以使用 Console.WriteLine 向它发送输出。好吃。

    现在您要实现的是服务控制管理器调用您的 OnStart 方法,然后该方法必须返回 OK 信号以让 SCM 知道您的应用程序启动正常。否则,SCM 会认为有问题并杀死您的应用程序。所以 OnStart 应该启动你的线程。因此,创建一个由您的线程(和 Main)运行的 Run() 方法,并让 OnStart 尽可能快地返回。

    我注意到我在您的代码示例中看不到任何内容:

    System.ServiceProcess.ServiceBase[] ServicesToRun; ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; System.ServiceProcess.ServiceBase.Run(ServicesToRun);

    我怀疑您的应用没有向 SCM 报告它已成功启动可执行文件中的“服务”。

    您希望您的应用启动,将“服务”移交给 SCM,让它知道您没问题,然后返回,此时您的服务现在使用自己的线程运行。

    请参阅这篇文章以了解详细介绍: http://msdn.microsoft.com/en-us/library/aa984464(v=vs.71).aspx

    【讨论】:

    • 答案是当你说“我注意到我在你的代码示例中没有看到任何这些:”我猜这没有添加到 Main() 因为我首先制作了一个控制台应用程序添加了一项服务
    【解决方案3】:
     partial class Service1 : ServiceBase
     {
        private Program program;
    
        public Service1()
        {
            InitializeComponent();
            program = new Program ();
        }
    
        protected override void OnStart(string[] args)
        {
            program.Start ();
        }
    
        protected override void OnStop()
        {
            program.Stop ();
        }
    }
    
    class Program
    {
        private Systems.Timers.Timer timer;
    
        public Program ()
        {
            timer = new System.Timers.Timer ();
            timer.Interval = 10000;
            timer.Elapsed += new ElapsedEventHandler (timer_Elapsed);
    
        }
    
        public void Start () 
        {
            timer.Enabled = true;
        }
    
        public void Stop ()
        {
            timer.Enabled = false;
        }
    
        public static void timer_Elapsed (object sender, EventArgs e)
        {
            EventLog.WriteEntry ("ProcessThread1", "Process1 Works");
        }
    }
    

    【讨论】:

      【解决方案4】:
      1. 你不会在你的代码中启动线程,所以:

        for (int i = 0; i < 3; i++)
        {
            new Thread(() => { processEventLogTesting(); }) { IsBackground = true }.Start();
        }
        
      2. 在您的processEventLogTesting() 处,除了错误的递归调用之外,您还创建了一个计时器,然后用timer1 = new System.Timers.Timer(); 覆盖它,这样它就不会触发。

        public static void processEventLogTesting()
        {
            System.Timers.Timer timer1 = new System.Timers.Timer();
            timer1.Interval = 10000;
            timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
            timer1.Start();
        }
        

      【讨论】:

        【解决方案5】:

        众所周知,Windows 服务很难调试。如果您没有收到任何其他消息,请尝试在 onstart 上暂停一下,您应该能够附加到它,然后查看问题所在。

        Nik 在这里有答案,但这可能对其他 Windows 服务有用!

        【讨论】:

        • 我总是调试我的服务,因为我有一个控制台应用程序项目,它将在我的调试器中运行服务逻辑。这对我来说效果很好。
        • 另一种调试方法是在您的 ServiceBase 中创建(例如)一个 Start() 方法。此方法调用 OnStart(null),然后使用 Timeout.Infinite 休眠。要使用,请调用 MyService.Start() 而不是 ServiceBase.Run()。然后你就可以用 F5 调试了。
        • 我确实放置了一个额外的睡眠循环,可以在调试器计算机上运行。然后我使用附加调试模式从 VS 调试环境中捕获该行。 code while (Environment.MachineName.ToUpper().StartsWith("CN")) { // 仅在测试调试器计算机上 -- 名称如 CNEMRE... Thread.Sleep(TimeSpan.FromSeconds(3)); } code
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多