2012-11-19 35 views
2

我做了一個簡單的Windows服務,但是當我嘗試啓動它,它與下面的消息會立即關閉:我如何保持我的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給出的消息與這個服務有什麼關係,因爲這會阻止任何服務運行,除非已經依賴它。

+3

您的代碼只運行一次,然後關閉。它的工作就像你寫的一樣。 –

+0

@Ramhound - 我確定計時器實際上是在'InitializeComponent();'方法調用中啓動的。然後代碼將運行多次。他可能只是從帖子中省略了代碼,但是有一種方法可以捕獲「OnTimeEvent」,所以你可以想象他已經對它的那部分進行了排序。 – hofnarwillie

回答

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... 
    } 
} 
+0

除了這個我顯然也有在創建文件時關閉流,所以: 'File.Create(@ 「C:\ ERRORLOG.TXT」);' 改爲: '文件。創建(@「c:\ ErrorLog.txt」)。Close();' –

+0

確實,我錯過了那一個。一般情況下,除非你有充分的理由使用Stream,否則我建議你使用'File'類的靜態方法,比如'File.WriteAllText()'來創建一個文件,而不用擔心鎖定和'File.AppendAllText()'來追加文本而不必擔心流和鎖定。要模仿'WriteLine()',您可以簡單地將Environment.NewLine添加到您追加的內容中,例如'File.AppendAllText(@「c:\ ErrorLog.txt」,s + Environment.NewLine);'。您仍然需要捕獲錯誤(例如文件被其他進程鎖定,沒有權限等),但您不必擔心關閉它。 –

0

msdn

只要你使用的是定時器,你必須保持一個參考吧。由於 與任何託管對象有關,因此當 中沒有對它的引用時,Timer將進行垃圾回收。定時器仍處於活動狀態的事實 並不妨礙它被收集。

您不保留對Timer對象的任何引用。

嘗試修改此:

private static Timer _timer; 

這樣:

private Timer _timer; 

這:

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

這樣:

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

正如我可以看到你的代碼是結束...程序的。因此執行走向自然結束。這就是爲什麼你的服務也停止了,因爲它的執行結束了。