What is the point of the CancellationToken in IHostedService.StartAsync in asp .net core?
Asked Answered
H

1

6

I'm trying to implement a hosted service and I was wondering what I am expected to do with the CancellationToken in the IHostedService.StartAsync call.

There is quite a lot in the Microsoft documentation about the cancellation token in StopAsync being essentially a timeout (5s by default) that means graceful shutdown is supposed to happen within a reasonable timeframe.

But regarding the token in StartAsync, there is not much information. If anything, the documentation specifies that the implementation shouldn't await on long running initialisation processes and should just return a long running task. So if I support cancellation, should I pass the cancellation token to whatever creates that long running task? If yes, isn't cancelling this token a dumber version of StopAsync? Why would the framework ever do this?

And indeed, in Microsoft's own abstract BackgroundService, the implementation for StartAsyncactually completely ignores that token and creates a new one which will be cancelled on call to StopAsync...

So am I to think that the whole point of that initial token passed by the framework is actually to be used in blocking initialisation processes nonetheless (despite the doc advising against it) by overriding the virtual BackgroundService.StartAsync method? e.g.

public class MyBackgroundService : BackgroundService
{
    public override Task StartAsync(CancellationToken cancellationToken)
    {
        // Block the thread for initialisation with cancellation (replace Task.Delay by actual initialisation)
        Task.Delay(TimeSpan.FromSeconds(10), cancellationToken).GetAwaiter().GetResult();

        // Start the long running task proper
        return base.StartAsync(cancellationToken);
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // some long running process (write some actual background running code here)
        return Task.Factory.StartNew(_ => {while(!stoppingToken.IsCancellationRequested){}}, null, stoppingToken);
    }
}
Hyetal answered 4/12, 2019 at 15:41 Comment(1)
It might not be due to specific usage of cancellation. The general rule is that each async method should have a cancellation token parameter. So that if the token is necessary in the future, it isn't a breaking change.Unbelief
C
12

The CancellationToken passed into the StartAsync can be used to determine if the start process should be canceled but as far as I understand, you already know that. This is written here.

Indicates that the start process has been aborted.

If you look at where StartAsync is called, you can see that the CancellationToken which is passed into the StartAsync function is linked with IHostApplicationLifetime.ApplicationStopping. As far as I understand, this token is just used if the shutdown of the application happens so early that not all hosted services have been fully started yet. However, I don't know if StopAsync will be called if the starting token is triggered (I'd have to dig further in the sources or search more in the docs).

To summarize:
The CancellationToken in the StartAsync-method should just be passed to any method called in StartAsync which supports cancellation. It will allow the app to shutdown gracefully in case the requested shutdown happens so early that the hosted service has not been fully started yet.

Cultured answered 4/12, 2019 at 17:41 Comment(1)
Hello @joelius , how about CancellationToken in StopAsync method , what is needed with that ? I am just confused with that ? I cannot find a place to consume it. Any advice will be appreciated.Homeomorphism

© 2022 - 2024 — McMap. All rights reserved.