3

这是 Windows 服务行为示例,其中托管服务在应用程序启动之前尝试连接 我有一个 .net core 2.2 控制台应用程序配置为作为 Windows 服务运行。我还配置了一个托管服务,它尝试无限期地建立与外部 tcp 服务器的连接,直到连接成功。

问题是当 windows 服务启动并且外部 tcp 服务器不可用时,windows 服务在“启动”状态下挂起,直到外部服务可以连接。该服务永远不会达到“运行”状态。尽管此行为与文档https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2&tabs=visual-studio#ihostedservice-interface一致,其中说“使用通用主机时,在触发 ApplicationStarted之前调用 StartAsync 。”,我想要的是在 Windows 服务完全启动后(即处于“运行”状态)开始托管服务。

我确实研究了使托管服务成为定时后台服务的方面,其初始延迟足以完全启动 Windows 服务,而不是使用 IApplicationLifetime.ApplicationStarted 注册托管服务,但这感觉像是一种估计 Windows 所需时间的骇人听闻的方法服务开始。相反,我正在寻找一种在 Windows 服务完全启动后开始托管服务的优雅方式。

托管服务代码

 public class TcpHostedService : BackgroundService
    {
        private readonly IPostBridgeConnection _client;
        private readonly IApplicationLifetime _lifetime;
        private readonly ILogger<TcpHostedService> _logger;

        public TcpHostedService(IPostBridgeConnection client,
            IApplicationLifetime lifetime,
            ILogger<TcpHostedService> logger)
        {
            _client = client ?? throw new ArgumentNullException(nameof(client));
            _lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("tcp connection - registering start and stop events with application lifetime");
            _lifetime.ApplicationStarted.Register(() => OnStarted(stoppingToken));
            _lifetime.ApplicationStopping.Register(() => OnStopping(stoppingToken));
            _lifetime.ApplicationStopped.Register(() => OnStopped(stoppingToken));
            _logger.LogInformation("tcp connection  - registered start and stop events with application lifetime");

            _logger.LogInformation("tcp connection  backgroundService is starting");
            return Task.CompletedTask;
        }

        #region lifetime events
        private void OnStarted(CancellationToken t)
        {
            _logger.LogInformation("tcp connection onstarted event triggered");
            _client.Init(t);
        }

        private void OnStopping(CancellationToken t)
        {
            _logger.LogInformation("tcp connection onstopping event triggered");
            _client.Dispose(t);
        }

        private void OnStopped(CancellationToken t)
        {
            _logger.LogInformation("tcp connection onstopped event triggered");
            _logger.LogInformation("tcp connection is disposed");
        }

该服务在 Program.cs 中注册为

services.AddHostedService<TcpHostedService>();
4

1 回答 1

4

IApplicationLifetime.ApplicationStarted您展示的方式,使用令牌(或在 .NET Core 3.0 中)注册回调IHostApplicationLifetime看起来应该可以工作。那里的限制是回调是同步的,所以你不应该async在那里做任何事情。

但是,就个人而言,我更喜欢您最初描述的方法 - 制作IHostedServiceaBackgroundService以便它不会阻止启动,并使用Polly重试任何瞬态错误,直到客户端能够连接。

于 2019-09-27T21:23:29.943 回答