Как выполнить длительную инициализацию в ASP.Net Core WebApp, работающем как служба Windows? - PullRequest
0 голосов
/ 07 мая 2019

Существует множество ресурсов, в которых обсуждается, как обрабатывать длительную инициализацию (например, миграцию базы данных) в ASP.Net Core WebApp (см. здесь или здесь , для пример). Текущий консенсус, по-видимому, заключается в том, чтобы выполнить такую ​​инициализацию в Program.cs после того, как IWebHost был собран, но до его фактического запуска.

Это прекрасно работает при запуске WebApp в консоли или в IIS. Но при работе в качестве службы Windows у меня истекает 30-секундный тайм-аут ОС.

Вот некоторый код, который иллюстрирует проблему. Полный (но все же минимальный) пример можно найти здесь .

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        if (args.Contains("--initialize"))
            LongRunningInitialization(host);

        if (args.Contains("--console"))
            host.Run();
        else
            host.RunAsService();
    }

    private static void LongRunningInitialization(IWebHost host)
    {
        var logger = host.Services.GetRequiredService<ILogger<Program>>();
        logger.LogInformation("Doing long-running initialization (sleep for 35 seconds)");
        Task.Delay(35000).Wait();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
public class Startup
{
    public void Configure(IApplicationBuilder app)
        => app.Run(async (context) => await context.Response.WriteAsync("Hello World!"));
}
public class MyWebHostService : WebHostService
{
    private readonly ILogger<MyWebHostService> Logger;

    public MyWebHostService(IWebHost host)
        : base(host)
    {
        AutoLog = true;
        CanHandlePowerEvent = false;
        CanHandleSessionChangeEvent = false;
        CanPauseAndContinue = false;
        CanShutdown = false;
        CanStop = true;
        ServiceName = "MyTestService";

        Logger = host.Services.GetRequiredService<ILogger<MyWebHostService>>();
    }

    protected override void OnStarting(string[] args)
    {
        Logger.LogInformation("MyWebHostService.OnStarting");

        //  This doesn't help...
        RequestAdditionalTime(60000);

        base.OnStarting(args);
    }

    protected override void OnStarted()
    {
        Logger.LogInformation("MyWebHostService.OnStarted");
        base.OnStarted();
    }
}
public static class MyWebHostServiceExtensions
{
    public static void RunAsService(this IWebHost host)
    {
        var myWebHostService = new MyWebHostService(host);
        ServiceBase.Run(myWebHostService);
    }
}

Если я зарегистрируюсь и запустлю этот сервис следующим образом:

sc.exe create MyTestService DisplayName= "My Test Service" binpath= "....\WindowsServiceStartupTest.dll --initialize"
sc.exe start MyTestService

Я получаю следующее сообщение об ошибке:

Служба не ответила на запрос запуска или управления своевременно.

Без длительной инициализации служба запускается нормально.

Обратите внимание, что в переопределении OnStarting я пытаюсь увеличить время ожидания, но это не работает. Похоже, OnStarting вызывается после длительной инициализации (слишком поздно).

Итак, мой вопрос: как правильно запустить длительную инициализацию для Windows Server WebApp? Есть ли способ запросить дополнительное время у ОС ранее в процессе запуска?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...