0

我有一个 Windows 服务,它会自行静默停止。以下是相关代码:

OnStart() 方法:

    protected override void OnStart(string[] args)
    {
        try
        {
            InitializeLogging();

            // we don't DO command line arguments
            if (args.Length > 0)
            {
                eventLog.WriteEntry("All command line arguments are ignored.  You must edit the app.config file manually to make changes to what watchers are run.");
                throw new ArgumentException("Command line arguments are ignored.");
            }

            ReadAppConfig();
            RecalculateStartTimes();
            InitializeWatchers();

        }
        catch (Exception e)
        {
            eventLog.WriteFormattedEntry("Error on Start: {0}", e.Message);
        }
        finally
        {
            eventLog.WriteEntry("Service start completed");
        }
    }

OnStop() 方法:

    protected override void OnStop()
    {
        eventLog.WriteEntry("Service stopped.");
    }

InitializeWatchers() 方法:

    private void InitializeWatchers()
    {
        try
        {

            var watchers = _watcherSection.Watchers.ToList<WatcherElement>();

            eventLog.WriteEntry(string.Format("Initializing {0} watchers.", watchers.Count()));

            var obsWatchers = watchers.ToObservable();
            obsWatchers.SelectMany(
                watcher =>
                    Observable.Timer(watcher.StartTime, TimeSpan.FromHours(watcher.Interval))
                              .SelectMany(
                                    Observable.FromAsync(
                                      async () => new
                                      {
                                          watcher,
                                          response = await CheckFolder(watcher.Path)
                                      })))
                              .Subscribe(
                                    onNext: x =>
                                    {
                                        eventLog.WriteFormattedEntry("\nWatcher: {0}, Time:{1}", x.watcher.Name, DateTimeOffset.Now);
                                        if (x.response.Success)
                                            eventLog.WriteFormattedEntry("| Success!\n| Value: '{0}'\n| Message: {0}", x.response.Value, x.response.Message);
                                        else
                                            eventLog.WriteFormattedEntry("| FAILURE!\n| Value: '{0}'\n| Message: {0}\n| Errors: '{0}'", x.response.Value, x.response.Message, x.response.Exceptions.First());
                                    },
                                    onError: e =>
                                        {
                                            var err = e;
                                            var sb = new StringBuilder();
                                            sb.AppendLine("The observer threw an error:")
                                              .AppendFormatLine("| Message: {0}", e.Message);

                                            while (e.InnerException != null)
                                            {
                                                sb.AppendFormatLine("| Inner: {0}", e.InnerException.Message);
                                                e = e.InnerException;
                                            }

                                            sb.AppendLine();
                                            eventLog.WriteEntry(sb.ToString());
                                            throw err;
                                        });

            eventLog.WriteEntry("about to wait.");
            obsWatchers.Wait();
            eventLog.WriteEntry("passed the wait");
        }
        catch (Exception e)
        {
            eventLog.WriteFormattedEntry("Exception thrown in InitializeWatchers(WatchersSection): {0}", e.Message);
            throw;
        }
    }

当我运行此代码时,服务正常启动。事件日志记录三个事件:

  1. 服务和日志记录开始。
  2. 初始化 1 个观察者。
  3. 服务启动完成。

......它停止了。我必须手动刷新服务窗口,但它退出运行。我没有收到任何错误或任何其他 eventLog 条目。

令人沮丧的是,这段代码可以完美地用作控制台应用程序。我已将所有 eventLog.WriteEntry() 更改为 Console.WriteLine(),但除此之外,代码相同并按预期执行。

任何智慧将不胜感激。

4

2 回答 2

1

我怀疑服务控制管理器正在终止您的服务,因为它没有从OnStart超时窗口(30 秒,IIRC)内返回。

我有一篇关于托管服务基础的博文,它基于BCL 团队的一篇博文。请注意,MSDN 文档不足;您必须了解 BCL 团队博客文章中的信息才能正确编写托管服务。

于 2013-09-04T21:43:42.410 回答
0

而不是使用obsWatchers.Wait()哪些块并导致斯蒂芬所说的问题,只是异步订阅。

将此属性添加到您的课程中:

private SingleAssignmentDisposable _subscription = new SingleAssignmentDisposable();

将此添加到您的OnStop方法中:

_subscription.Dispose();

在您的InitializeWatchers()中,消除嵌套调用Subscribe并替换obsWatchers.Wait()为调用订阅,如下所示:

private void InitializeWatchers()
{
    try
    {

        var watchers = _watcherSection.Watchers.ToList<WatcherElement>();

        eventLog.WriteEntry(string.Format("Initializing {0} watchers.", watchers.Count()));

        var obsWatchers = watchers.ToObservable();
        _subscription.Disposable = obsWatchers
            .SelectMany(watcher => Observable
                .Timer(watcher.StartTime, TimeSpan.FromHours(watcher.Interval))
                .SelectMany(_ => Observable.FromAsync(async () => new
                      {
                          watcher,
                          response = await CheckFolder(watcher.Path)
                      })))
             .Subscribe(
                 onNext: x =>
                 {
                     eventLog.WriteFormattedEntry("\nWatcher: {0}, Time:{1}", x.watcher.Name, DateTimeOffset.Now);
                     if (x.response.Success)
                         eventLog.WriteFormattedEntry("| Success!\n| Value: '{0}'\n| Message: {0}", x.response.Value, x.response.Message);
                     else
                         eventLog.WriteFormattedEntry("| FAILURE!\n| Value: '{0}'\n| Message: {0}\n| Errors: '{0}'", x.response.Value, x.response.Message, x.response.Exceptions.First());
                 },
                 onError: e =>
                 {
                     var err = e;
                     var sb = new StringBuilder();
                     sb.AppendLine("The observer threw an error:")
                       .AppendFormatLine("| Message: {0}", e.Message);

                     while (e.InnerException != null)
                     {
                         sb.AppendFormatLine("| Inner: {0}", e.InnerException.Message);
                         e = e.InnerException;
                     }

                     sb.AppendLine();
                     eventLog.WriteEntry(sb.ToString());
                     throw err;
                 });
        eventLog.WriteEntry("passed the wait");
    }
    catch (Exception e)
    {
        eventLog.WriteFormattedEntry("Exception thrown in InitializeWatchers(WatchersSection): {0}", e.Message);
        throw;
    }
}
于 2013-09-05T14:36:21.283 回答