【问题标题】:Host .NET Core console application like Windows Service托管 .NET Core 控制台应用程序,例如 Windows 服务
【发布时间】:2018-07-16 17:36:55
【问题描述】:

我的工作进程是一个 .net 核心控制台应用程序。如何像 Windows 服务一样托管它?

因为在当前的实现中,我认为如果我将它打包成类似 nssm 的东西,它会因为 Console.ReadKey(); 而卡住。但我仍然需要处理停止事件。

public class Program
{
    private Program()
    {
    }

    public static void Main()
    {
        var services = new ServiceCollection();
        var startup = new Startup();
        startup.ConfigureServices(services);

        var serviceProvider = services.BuildServiceProvider();

        var workerService = serviceProvider.GetService<WorkerService>();


        workerService.Run();

        Console.WriteLine("Listening for messages. Hit any key to quit.");
        Console.ReadKey();

        workerService.Stop();
    }
}

【问题讨论】:

  • 这是 ASP.NET Core 应用程序还是标准 .NET Core 控制台应用程序?如果是这样,有一些方法可以将 .NET 控制台应用程序“托管”为 Windows 服务(不像内置的 int ASP.NET 核心方法那么简单)ben-morris.com/…

标签: .net .net-core


【解决方案1】:

在 .NET Core 2.1 中,您可以使用 Generic Host 类来创建和运行类似服务/守护程序的应用程序。

您可以以几乎与 ASP.NET Core 应用程序相同的方式配置和运行您的应用程序。尽管有文章标题,但这并不特定于 ASP.NET Core,Generic Host Builder 是通过不依赖 ASP.NET Core 的 Microsoft.Extensions.Hosting 包部署的。

主要方法可能如下所示:

public static async Task Main(string[] args)
{
    var host = new HostBuilder()
        .UseConsoleLifetime()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddLogging();
            services.AddHostedService<LifetimeEventsHostedService>();
            services.AddHostedService<TimedHostedService>();
        })
        .Build();

    await host.RunAsync();
}

只要应用程序运行就需要运行的服务应该实现IHostedService。这在Background tasks with hosted services 中有描述。

UseConsoleLifetime() 调用将主机配置为检查Ctrl+C 并终止应用程序。发生这种情况时,主机将调用实现IHostedService 接口的任何已配置服务的StopAsync 方法。

RunAsync() 被调用时,它将调用任何实现IHostedService 的服务的StartAsync 方法。

您也可以调用RunConsoleAsync() 来配置控制台生命周期并启动服务,而无需额外调用UseConsoleLifetime()

RunAsyncRunConsoleAsync 将阻塞直到主机终止。您可以使用StartStartAsync 来启动服务并继续处理例如控制台输入或外部命令。当需要终止应用程序时,例如响应exit 输入,您可以调用StopAsync

例如:

host.Start();

Console.WriteLine("Type exit or Ctrl+C to exit");
while(Console.ReadLine() !="exit")
{
    //..
}

await host.StopAsync();

当然,这可以用于更重要的事情,比如监听端口上的命令

【讨论】:

    【解决方案2】:

    不要使用自定义停止信号,而是使用CTRL-C标准 来中断您的流程。 Console.CancelKeyPress 中有一些示例展示了如何对该事件做出反应,例如,您可以在其中放置 workerService.Stop() 语句。

    nssm 之类的工具可以配置为发送CTRL-C 信号以启动服务关闭,并且可以预期任何包装系统都将提供类似的功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      相关资源
      最近更新 更多