dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.5k stars 10.04k forks source link

ConsoleLifetime being executed after HostedService #17483

Closed uabarahona closed 4 years ago

uabarahona commented 4 years ago

Describe the bug

Hi,

Not sure if I am using the generic host correctly but doing some playing with it I found when using RunConsoleAsync() is the HostedService whose methods are executed first, so I was wondering shouldn't ConsoleLifetime be executed first?

That way I am able to end application before any work on HostedServices happens

To Reproduce

Program.cs

static async Task Main(string[] args)
{
    await Host
        .CreateDefaultBuilder()
        .ConfigureServices((hostContext, services) => {
            services.AddHostedService<ConsoleApplication>();
        })
        .RunConsoleAsync();
}

ConsoleApplication.cs

public class ConsoleApplication : IHostedService
{
    private readonly ILogger<ConsoleApplication> logger;

    public ConsoleApplication(ILogger<ConsoleApplication> logger)
    {
        this.logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation("Starting application");

        Task.Run(() => {
            bool quit = false;
            while (!quit) {
                Console.WriteLine("Enter your action: ");
                string action = Console.ReadLine();
                quit = action == "quit";
            }

        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation("Ending the application");

        return Task.CompletedTask;
    }
}

image

Further technical details

Tratcher commented 4 years ago

I don't quite follow. That Task.Run makes the order indeterminate. The main conflict here seems to be trying to use both the console logger and console input at the same time. You'd be better off disabling the console logger and using some other kind of logging if you want to write an interactive console application.

uabarahona commented 4 years ago

Thanks for the answer, yeah I am probably not using generic host in the correct way to make a interactive console a doc on this could be great! but my main concern is about the order of logs which could not be a big deal.

For example here: https://github.com/aspnet/Extensions/blob/master/src/Hosting/samples/GenericHostSample/ProgramHelloWorld.cs

There is two hosted services and the host is being executing with RunConsoleAsync but when checking logs we can see the following: image

Logs from services are at the beginning while the RunConsoleAsync logs are after that, I was expecting the RunConsoleAsync to execute at the beginning at all but I could wrong, could you please confirm me this?

Tratcher commented 4 years ago

RunConsoleAsync is effectively just an alias for Host.RunAsync(). That starts all of the services and then the ConsoleLifetime logs that everything has successfully started. This is the expected behavior.

I could see re-ordering these lines so that the CTL+C log was last. https://github.com/aspnet/Extensions/blob/cda774390962745f07baa11069f46aec489f4c61/src/Hosting/Hosting/src/Internal/ConsoleLifetime.cs#L69-L71

uabarahona commented 4 years ago

Got it, so ConsoleLifetime makes sure all services are started correctly and only then logs that success. Now it make sense for me.

And yes having CTL+C and the end might be better.

Thanks for all.

ghost commented 4 years ago

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.