0

I am using .NET 7 and in that I am implementing BackgroundService. While implementing BackgroundService I want to log when service started and when service stopped. But I am not able to log when service stopped.

Following is my code -

public class BackgroundWorkerService : BackgroundService
{
    readonly ILogger<BackgroundWorkerService> _logger;

    public BackgroundWorkerService(ILogger<BackgroundWorkerService> logger)
    {
        _logger = logger;
    }

    protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Service Started");

        while (stoppingToken.IsCancellationRequested is false)
        {
            _logger.LogInformation("Service running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

In this above code somewhere I want to put this line -

_logger.LogInformation("Service Stopped");

But when I am writing this above line in while loop or after the while loop. And then running my website and then closing it, "Service Stopped" is not getting logged in console. What should I do ?

What I tried -

1.

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Service Started");

        while (stoppingToken.IsCancellationRequested is false)
        {
            _logger.LogInformation("Service running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }

        _logger.LogInformation("Service Stopped");
    }

2.

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Service Started");

        while (stoppingToken.IsCancellationRequested is false)
        {
            _logger.LogInformation("Service running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }

        if (stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Service Stopped");
        }
    }

3.

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Service Started");

        while (stoppingToken.IsCancellationRequested is false)
        {
            _logger.LogInformation("Service running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);

            if (stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Service Stopped");
            }
        }
    }

4.

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Service Started");

        while (stoppingToken.IsCancellationRequested is false)
        {
            _logger.LogInformation("Service running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }

public async override Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Service Stopped");
    
        await base.StopAsync(cancellationToken);
    }
  • And how do you stop the application? Not every type of application stoppage perform graceful shutdown. – Guru Stron Mar 23 '23 at 09:46
  • @GuruStron just by closing on which ever browser my website is running. i.e clicking on (x) symbol on browser. – Abhay Singh Mar 23 '23 at 09:50
  • Would you try `stoppingToken.Register(() =>_logger.LogInformation("Service Stopped"));` with 1. sample after start the service ? – OnePage Mar 23 '23 at 09:52
  • Try running app with `dotnet run` from console and then stopping it with CNTRL+C (for example my IDE does not stop the site upon closing web page) – Guru Stron Mar 23 '23 at 09:53
  • @GuruStron, you shall implement `IHostApplicationLifetime` for perform graceful shutdown. For full sample: https://stackoverflow.com/a/58424476/3805533. He is probably asking for when service completed or canceled by user – OnePage Mar 23 '23 at 09:57
  • @OnePage usually hosted services are used within host (web one in case of ASP) And AFAIK it already implements that. – Guru Stron Mar 23 '23 at 09:59
  • @GuruStron I am not sure but there is other option as Kestrel, it might not be auto implement stopped / stopping logging. – OnePage Mar 23 '23 at 10:03
  • @OnePage the question you have linked is not about **implementing** the lifetime, it is using an existing one. Hosted services already should leverage this feature - the passed cancellation tokens are specifically for graceful shutdown. – Guru Stron Mar 23 '23 at 10:07
  • @OnePage yes I tried stoppingToken.Register method you said it is not working. – Abhay Singh Mar 23 '23 at 10:08
  • @GuruStron I am using visual studio, and in that CTRL + C does not work for closing the website. – Abhay Singh Mar 23 '23 at 10:10
  • @AbhaySingh please read again my suggestion. It is about starting website via CLI – Guru Stron Mar 23 '23 at 10:11
  • I got answer of this question from this [Link](https://stackoverflow.com/questions/67379471/windows-service-using-net-core-backgroundservice-how-to-gracefully-stop#:~:text=public%20class%20Worker%20%3A%20BackgroundService%20%7B%20protected%20override,%7B%20continue%3B%20%7D%20%7D%20_logger.LogInformation%20%28%22Stopped%22%29%3B%20%7D%20%7D) – Abhay Singh Mar 24 '23 at 13:30

1 Answers1

1

You want to place it in a finally. The normal way for background services to shut down is to have their cancellation token cancelled, and the normal way to respond to cancellation is with an OperationCanceledException.

public class BackgroundWorkerService : BackgroundService
{
  readonly ILogger<BackgroundWorkerService> _logger;

  public BackgroundWorkerService(ILogger<BackgroundWorkerService> logger)
  {
    _logger = logger;
  }

  protected async override Task ExecuteAsync(CancellationToken stoppingToken)
  {
    _logger.LogInformation("Service Started");

    try
    {
      while (stoppingToken.IsCancellationRequested is false)
      {
        _logger.LogInformation("Service running at: {time}", DateTimeOffset.Now);
        await Task.Delay(1000, stoppingToken);
      }
    }
    finally
    {
      _logger.LogInformation("Service Stopped");
    }
  }
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810