aspnet / Hosting

[Archived] Code for hosting and starting up an ASP.NET Core application. Project moved to https://github.com/aspnet/Extensions and https://github.com/aspnet/AspNetCore
Apache License 2.0
552 stars 312 forks source link

Keeping background service alive forever #1546

Closed tymtam2 closed 5 years ago

tymtam2 commented 6 years ago

Let's say my application has been built in the following way:

public sealed class StartupTask : IBackgroundTask
{

    /// <summary>
    /// The Background Application template is documented at <see href="https://docs.microsoft.com/en-us/windows/iot-core/develop-your-app/backgroundapplications">Developing Background Applications</see>
    /// </summary>
    /// <param name="taskInstance">An interface to an instance of the background task. The system creates this instance when the task has been triggered to run.</param>
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        (...) //Configure logger etc.

        Forever();

        // We should never end up here
    }

    private void Forever()
    {
        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddSingleton(Log.Logger);
                (...)//Register other services here
                services.AddHostedService<MainService>();
            });

        try
        {
            var host = builder.Build();

            using (host)
            {
                // This blocks forever
                host.Run();
            }
        }
        catch (Exception ex)
        {
            // Note: Potential dependency injection issues are triggered when StartAsync is called.
            Log.Logger.Error(ex, "Failed to start.");
            throw;
        }
    }
}

And then

public class MainService : BackgroundService
{
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        (...)//Kick off different long running and 'forever' tasks here

        //Question: Is this the correct canonical way to keep the service 'alive'?
                    //Update 18/Sep/2018 after David F. replied 
        //was: return Task.Delay(Timeout.Infinite, stoppingToken);
                   await Task.Delay(Timeout.Infinite, stoppingToken);
    }
}   

My question is:

Is return Task.Delay(Timeout.Infinite, stoppingToken); in ExecuteAsync the correct canonical way to keep the service 'alive'?

davidfowl commented 6 years ago

Yep, that's fine, it'll just pause until the token fires. I'm assuming that you don't have another way to wait on the other long running tasks itself?

tymtam2 commented 6 years ago

Hi @davidfowl

I'm planning to run the long running/forever tasks in a fire_and_forget way.

Are you suggesting that

var tA = StartForeverTaskA(); 
var tB = StartForeverTaskB(); 
var tC = StartForeverTaskC(); 
var tD = StartForeverTaskD(); 

await Task.WhenAll(new [] {tA,tB,tC,tD});

or even

StartForeverTaskA(); // fire and forget
StartForeverTaskB(); // fire and forget
StartForeverTaskC(); // fire and forget
await StartForeverTaskD(); //never returns; 

would be equally 'correct'?

davidfowl commented 6 years ago

Yes, passing the token to each of them so that they would try to unwind if the stoppingToken is fired.

aspnet-hello commented 5 years ago

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.