【问题标题】:How do i keep my windows service alive?如何让我的 Windows 服务保持活力?
【发布时间】:2012-11-19 14:09:06
【问题描述】:

我制作了一个简单的 Windows 服务,但是当我尝试启动它时,它会立即关闭并显示以下消息:

本地计算机上的 ConsumerService 服务启动然后停止。如果某些服务没有被其他服务或程序使用,它们会自动停止。

以下是我尝试运行的服务:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        var servicesToRun = new ServiceBase[] 
                                          { 
                                              new ConsumerService() 
                                          };
        ServiceBase.Run(servicesToRun);
    }
}

public partial class ConsumerService : ServiceBase
{
    private readonly MessageConsumer<ClickMessage> _messageconsumer;
    private readonly SqlRepository _sqlrep;
    private static Timer _timer;
    public ConsumerService()
    {
        InitializeComponent();

    }

    protected override void OnStart(string[] args)
    {
        try
        {
            File.Create(@"c:\ErrorLog.txt");
            WriteToFile("Has started : " + DateTime.UtcNow);
            var t = new Timer(OnTimeEvent, null, 1000, 1000);
        }
        catch (Exception e)
        {
            WriteToFile("Error : " + e.Message);
        }
    }

    private void OnTimeEvent(object state)
    {
        WriteToFile("The time is : " + DateTime.UtcNow);
    }

    protected override void OnStop()
    {
        WriteToFile("Has stopped : " + DateTime.UtcNow);
    }

    private static void WriteToFile(string s)
    {
        var stream = File.AppendText(@"c:\ErrorLog.txt");
        stream.WriteLine(s);
    }
}

如您所见,它只是一个简单的计时器,每 1 秒向文件写入一行,所以我很困惑为什么这会阻止服务运行。我也很难看出 windows 给出的消息与该服务有什么关系,因为这会阻止任何服务运行,除非某些东西已经依赖于它。

【问题讨论】:

  • 您的代码运行一次然后关闭。就像你写的那样工作。
  • @Ramhound - 我确定计时器实际上是在 InitializeComponent(); 方法调用中启动的。然后代码将运行多次。他可能只是省略了帖子中的代码,但是有一个方法可以捕获OnTimeEvent,所以你可以想象他已经对这部分进行了排序。

标签: c# windows-services


【解决方案1】:

这很可能是由于主线程中未处理的错误。要验证这一点,请检查事件日志,但通过快速查看您的代码,函数 WriteToFile 有可能崩溃并导致整个服务停止运行。

实际上它应该崩溃,因为您让流处于打开状态(因此文件被锁定)并且第二次尝试打开它会导致错误。

将代码更改为此,它应该可以防止此类崩溃,并修复您保持文件锁定的错误:

private static void WriteToFile(string s)
{
    try
    {
        using (var stream = File.AppendText(@"c:\ErrorLog.txt"))
        {
            stream.WriteLine(s);
            stream.Close();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("error writing to file: " + e);
        //...or any other means of external debug...
    }
}

【讨论】:

  • 除此之外我显然还必须在创建文件时关闭流,所以:File.Create(@"c:\ErrorLog.txt"); 更改为:File.Create(@"c:\ErrorLog.txt").Close();
  • 没错,我错过了那个。一般来说,除非您有充分的理由使用 Stream,否则我建议您使用 File 类静态方法,如 File.WriteAllText() 来创建文件而不用担心锁定和 File.AppendAllText() 附加文本而不必担心流和锁定.要模仿WriteLine(),您可以简单地将 Environment.NewLine 添加到您附加的内容中,例如File.AppendAllText(@"c:\ErrorLog.txt", s + Environment.NewLine);。您仍然需要捕获错误(例如,文件被其他进程锁定,没有权限等),但您不必担心关闭它。
【解决方案2】:

正如我所见,您的代码正在结束...因此程序的执行自然而然地结束了。这就是您的服务也停止的原因,因为它的执行结束了。

【讨论】:

    【解决方案3】:

    来自msdn

    只要您使用 Timer,就必须保留对它的引用。作为 对于任何托管对象,Timer 在 没有引用它。计时器仍然处于活动状态的事实 不会阻止它被收集。

    您没有保留对您的 Timer 对象的任何引用。

    尝试改变这个:

    private static Timer _timer;
    

    到这里:

    private Timer _timer;
    

    还有这个:

    var t = new Timer(OnTimeEvent, null, 1000, 1000);
    

    到这里:

    _timer = new Timer(OnTimeEvent, null, 1000, 1000);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 2021-06-01
      • 1970-01-01
      • 2013-05-10
      相关资源
      最近更新 更多