Home > OS >  Why doesn't Background Service stop in C#?
Why doesn't Background Service stop in C#?

Time:01-08

I'm trying manually stop the class that inherit from BackgroundService.

ExampleService.cs

public class ExampleService : BackgroundService, IExampleService
{
    private readonly ILogger<ExampleService> _logger;
    private bool stopRequested { get; set; }

    public ExampleService(ILogger<ExampleService> logger)
    {
        _logger = logger;
    }
    public async Task Stoping(CancellationToken token)
    {
        _logger.LogInformation("Stoping");
        stopRequested = true;
        await StopAsync(token);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var count = 0;
        while (!stoppingToken.IsCancellationRequested && !stopRequested)
        {
            await Task.Delay(1000, stoppingToken);
            _logger.LogInformation("Service is working {0}", count  );
        }
    }
}
public interface IExampleService
{
    Task Stoping(CancellationToken token = default);

}

Call from API

[HttpGet("stoptask2")]
public async Task<IActionResult> Get()
{
    await exampleService.Stoping();
    return Ok();
}

But the service doesn't stop. I know IHostApplicationLifetime is working but all application is stopping. I don't want this.

I have tried How to cancel manually a BackgroundService in ASP.net core but it doesn't work.

I know I should stop the service using stoppingToken in ExecuteAsync, but how?

CodePudding user response:

I think that the CancellationToken in the Stopping and Execute methods cannot process because they are different objects. So if you use this figure, you will solve the problem.

public class ExampleService : BackgroundService, IExampleService
{
    private readonly ILogger<ExampleService> _logger;
    private CancellationToken cancellationToken = new CancellationToken();
    private static bool stopRequested = true;

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

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var count = 0;
        while (!stoppingToken.IsCancellationRequested)
        {
            if (!stopRequested)
            {
                await base.StopAsync(stoppingToken);
            }
            await Task.Delay(3000, stoppingToken);
            _logger.LogInformation("ExampleService is working {0}", count  );
           
           
        }
    }

    public void Stoping() => stopRequested = false;
}
}

public interface IExampleService
{
    void Stoping();
}

Program.cs

builder.Services.Configure<HostOptions>(hostOptions =>
{
    hostOptions.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore;
});
builder.Services.AddHostedService<ExampleService>();
builder.Services.AddSingleton<IExampleService,ExampleService>();

CodePudding user response:

Without seeing the actual registration I can only guess, but I think problem is the registration - AddHostedService creates one service descriptor and when you register IExampleService it will create another unrelated one, so you have two different instances of service. Personally I would just use the separation of concerns principle and introduce separate service like IStopper which would have two methods Stop and IStopped (or expose a cancelation toke instead of the second one), but if you want to keep your current class/interface structure - then be sure to provide registration which will result in only one instance:

builder.Services.AddSingleton<ExampleService>(); // singleton
builder.Services.AddSingleton<IExampleService>(s => s.GetRequiredService<ExampleService>()); // reabstract as interface
builder.Services.AddHostedService<ExampleService>(s => s.GetRequiredService<ExampleService>()); // reabstract as hosted service

CodePudding user response:

Have you tried making an entity solely based on the stop function on? Make a few lines of code stating what should be stopped. You have to tell the computer what to stop specifically and what to continue.

  • Related