Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

422
Visualizações
The "correct" way to create a .NET Core console app without background services

I'm building a simple .NET Core console application that will read in basic options from the command line, then execute and terminate without user interaction. I'd like to take advantage of DI, so that lead me to using the .NET Core generic host.

All of the examples I've found that build a console app create a class that either implements IHostedService or extends BackgroundService. That class then gets added to the service container via AddHostedService and starts the application's work via StartAsync or ExecuteAsync. However, it seems that in all of these examples, they are implemementing a background service or some other application that runs in a loop or waits for requests until it gets shut down by the OS or receives some request to terminate. What if I just want an app that starts, does its thing, then exits? For example:

Program.cs:

namespace MyApp
{
    using System;
    using System.Threading.Tasks;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;

    public static class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).RunConsoleAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseConsoleLifetime()
                .ConfigureLogging(builder => builder.SetMinimumLevel(LogLevel.Warning))
                .ConfigureServices((hostContext, services) =>
                {
                    services.Configure<MyServiceOptions>(hostContext.Configuration);
                    services.AddHostedService<MyService>();
                    services.AddSingleton(Console.Out);
                });
    }
}

MyServiceOptions.cs:

namespace MyApp
{
    public class MyServiceOptions
    {
        public int OpCode { get; set; }
        public int Operand { get; set; }
    }
}

MyService.cs:

namespace MyApp
{
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Options;

    public class MyService : IHostedService
    {
        private readonly MyServiceOptions _options;
        private readonly TextWriter _outputWriter;

        public MyService(TextWriter outputWriter, IOptions<MyServiceOptions> options)
        {
            _options = options.Value;
            _outputWriter = outputWriter;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _outputWriter.WriteLine("Starting work");

            DoOperation(_options.OpCode, _options.Operand);

            _outputWriter.WriteLine("Work complete");
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            _outputWriter.WriteLine("StopAsync");
        }

        protected void DoOperation(int opCode, int operand)
        {
            _outputWriter.WriteLine("Doing {0} to {1}...", opCode, operand);

            // Do work that might take awhile
        }
    }
}

This code compiles and runs just fine, producing the following output:

Starting work
Doing 1 to 2...
Work complete

However, after that, the application will just sit there waiting until I press Ctrl+C. I know I could force the application to shutdown after the work is complete, but at this point, I feel like I'm not using IHostedService correctly. It seems as though it's designed for recurring background processes, and not simple console applications like this. However, in an actual application where DoOperation might take 20-30 minutes, I would like to take advantage of the StopAsync method to do cleanup before terminating. I also know I could create the service container myself and all that, but the .NET Core generic host already does a lot of stuff I would want to do anyway. It seems to be the right way to write console applications, but without adding a hosted service that kicks off the actual work, how do I get the app to actually do anything?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Instead of a hosted service, I would recommend the following;

using (var host = CreateHostBuilder(args).Build())
{
    await host.StartAsync();
    var lifetime = host.Services.GetRequiredService<IHostApplicationLifetime>();

    // do work here / get your work service ...

    lifetime.StopApplication();
    await host.WaitForShutdownAsync();
}
over 4 years ago · Santiago Trujillo Relatório

0

I know I could force the application to shutdown after the work is complete, but at this point, I feel like I'm not using IHostedService correctly.

I agree it does seem odd. I actually always stop the application at the end of all my IHostedService implementations. This is true even for long-running server apps. If a hosted service stops (or faults), then I explicitly want the application to end.

It does feel like this design was unfinished when .NET Core was pushed out. There are parts of the design that are made so that hosted services and their apps can have independent lifetimes, but since they can not be restarted, this just isn't useful in practice. So it ends up feeling like a poor design because the lifetimes can't be independent, but they are independent by default.

All of my hosted services end up tying their lifetime to the application lifetime.

finally
{
  _hostApplicationLifetime.StopApplication();
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda