在 .NET 8.0 中创建托管控制台应用程序

问题描述 投票:0回答:2

GenericHost/DefaultHost/WebHost 生态系统变化迅速,并且似乎缺乏需求组合。我正在使用 .NET 8.0。

使用截至 2024 年 1 月的稳定包,创建应用程序主机、配置日志记录/DI/配置并等待单个应用程序循环退出,同时提供 Ctrl+C 支持以提前优雅终止的控制台应用程序是什么样的?

使用以下代码,我在控制台上得到“RunAsync done”,然后是“stopped”,并正常关闭。如果我尝试使用 Ctrl+C 打破假“工作循环”,应用程序会立即退出,不会正常终止。

public class Program
{
    public static async Task Main(string[] args)
    {
        var hostBuilder = CreateDefaultApp(args);
        var host = hostBuilder.Build();

        Console.WriteLine("starting");
        var app = host.Services.GetRequiredService<TestApp>();
        await app.RunAsync();
        Console.WriteLine("stopped");
    }

    private static IHostBuilder CreateDefaultApp(string[] args)
    {
        var builder = Host.CreateDefaultBuilder();
        builder.ConfigureServices(conf =>
        {
            conf.AddSingleton<TestApp>();
        });
        builder.ConfigureLogging(conf =>
        {
            conf.ClearProviders();
            conf.AddConsole();
        });
        builder.UseConsoleLifetime();

        return builder;
    }
}

public class TestApp
{
    private readonly IHostLifetime _lifetime;
    private readonly IHostApplicationLifetime _appLifetime;

    public TestApp(IHostLifetime lifetime, IHostApplicationLifetime appLifetime)
    {
        _lifetime = lifetime;
        _appLifetime = appLifetime;
    }

    public async Task RunAsync()
    {
        var stopToken = _appLifetime.ApplicationStopping;

        Console.WriteLine("RunAsync starting");
        for (int i = 0; i < 10; i++)
        {
            if (stopToken.IsCancellationRequested)
            {
                Console.WriteLine("STOP");
                break;
            }
            
            await Task.Delay(250);
            Console.Write(i);
        }

        Console.WriteLine();
        Console.WriteLine("RunAsync done");
    }
}

我不在乎我的应用程序逻辑是否存在于这个有点独立的“TestApp”类中,或者作为托管服务运行,只要它可以注入依赖项,可以触发它自己的优雅(和不优雅)退出,运行在一个

async
上下文,并且可以使用 Ctrl+C 相对优雅地提前终止。我想使用 Microsoft 的
Host
提供程序来完成大部分配置,并且我不想“简单地”完成我自己的所有依赖项管理和配置。

.net console-application .net-8.0
2个回答
0
投票

您可以使用后台工作人员(请参阅.NET 中的工作人员服务)来实现您想要的行为。

我稍微修改了你的代码。请注意,您需要将项目模板更改为

Microsoft.NET.Sdk.Worker

public class Program
{
    public static async Task Main(string[] args)
    {
        var host = CreateDefaultApp(args).Build();

        Console.WriteLine("starting");
        await host.RunAsync();
        Console.WriteLine("stopped");
    }

    private static IHostBuilder CreateDefaultApp(string[] args)
    {
        var builder = Host.CreateDefaultBuilder();
        builder.ConfigureServices(conf =>
        {
            conf.AddHostedService<Worker>();
        });
        builder.ConfigureLogging(conf =>
        {
            conf.ClearProviders();
            conf.AddConsole();
        });

        return builder;
    }
}

public class Worker : BackgroundService
{
    private readonly IHostApplicationLifetime _HostApplicationLifetime;
    private readonly ILogger<Worker> _Logger;

    public Worker(IHostApplicationLifetime hostApplicationLifetime, ILogger<Worker> logger)
    {
        _HostApplicationLifetime = hostApplicationLifetime;
        _Logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Console.WriteLine("RunAsync starting");
        for (int i = 0; i < 10; i++)
        {
            if (stoppingToken.IsCancellationRequested)
            {
                Console.WriteLine("STOP");
                break;
            }

            await Task.Delay(250);
            Console.Write(i);
        }

        _Logger.LogInformation("test logging");

        Console.WriteLine();
        Console.WriteLine("RunAsync done");
        _HostApplicationLifetime.StopApplication();
    }
}

0
投票

对于您当前的代码 - 您正在设置主机但不使用它,您至少需要启动并等待它(基本上您正在侦听主机停止但它甚至没有开始停止):

var hostTask = host.StartAsync();
await app.RunAsync();
await hostTask;

基本上,您当前的代码看起来像是尝试利用通用主机 DI 基础设施创建您自己的托管(尽管如果您只需要 DI,则可以使用

ServiceCollection
)。

至于您的应用程序 - 考虑为您的TestApp使用托管服务(它们不是特定于 ASP.NET Core,

worker 服务
模板也使用它们)。

© www.soinside.com 2019 - 2024. All rights reserved.