简体   繁体   中英

Self-host in new minimalistic hosting model .NET 6

I have service in .NET 6. Something like this:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IService _service;

    public Worker(ILogger<Worker> logger, IService service)
    {
        _logger = logger;
        _service = service;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await _service.StartAsync().ConfigureAwait(false);
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken).ConfigureAwait(false);
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        await _service.StopAsync().ConfigureAwait(false);
        await base.StopAsync(stoppingToken).ConfigureAwait(false);
    }

I want to host web api .net core with controllers classes in it. But when I try to start application in ExecuteAsync, adding such code:

        var builder = WebApplication.CreateBuilder();
        builder.RegisterWeb();
        _app = builder.Build();
        _app.ConfigureWebApplication(builder.Environment);
        _app.Run();

I could not find anything working.

Are there other options besides trying to use Katana?

Code for support methods are standard:

    public static void ConfigureWebApplication(this 
    WebApplication app, IWebHostEnvironment environment)
    {
        if (environment.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseSwagger();
            app.UseSwaggerUI(c => 
           c.SwaggerEndpoint("/swagger/v1/swagger.json", 
          "E.WebApi v1"));
        }           
        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseEndpoints(endpoints => { endpoints.MapControllers(); 
       });
    }
    public static void RegisterWeb(this WebApplicationBuilder 
    builder)
    {
        builder.Services.AddControllers();
        builder.Services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = 
        "E.WebApi", Version = "v1" });
        });
        builder.WebHost.UseUrls("http://localhost:7153/");
    }

I've come here looking for an answer to the same question: can I run a web app hosting nested into a hosted service on a generic host? I do not see any obvious reasons why not, though I have not tried yet.

Anyway, I think I see the problem in your code.

You are trying to use _app.Run (which blocks the execution of the current thread) in ExecuteAsync (which is supposed to be asynchronous and non-blocing). That is why your hosted service can not even start.

The proper approach would be using await _app.RunAsync(stoppingToken) instead.

Side note:

At the time I am writing this, there is a bug in ASP.NET Core: WebApplication.RunAsync does not accept a cancellation token. See here: https://github.com/dotnet/aspnetcore/issues/44083

Fortunately, there is an extension method Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync which is called on IHost and accepts the token. WebApplication inplements IHost , so await _app.RunAsync(stoppingToken) will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM