You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8.0 WPF中正确使用.NET Generic Host与IHostApplicationLifetime

问题

我希望在.NET 8.0 WPF应用中使用.NET Generic Host,并借助IHostApplicationLifetime执行自定义的启动初始化与销毁清理操作。网上找到的方案仅将宿主用作DI容器,未调用host.Start()/host.StartAsync(),导致注入的IHostedService无法触发IHostApplicationLifetime的事件。

原方案代码:
Program.cs

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;

public class Program
{
    [STAThread]
    public static void Main()
    {
        var host = Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddSingleton<App>();
                services.AddSingleton<MainWindow>();
                // 注入自定义HostedService但无法触发生命周期事件
                services.AddHostedService<MyHostedService>();
            })
            .Build();

        var app = host.Services.GetService<App>();
        app?.Run();
    }
}

App.cs

using System.Windows;

public class App : Application
{
    readonly MainWindow mainWindow;

    public App(MainWindow mainWindow)
    {
        this.mainWindow = mainWindow;
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        mainWindow.Show();
        base.OnStartup(e);
    }
}

MyHostedService.cs

public class MyHostedService : IHostedService
{
    public MyHostedService(IHostApplicationLifetime appLifetime)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
    }

    public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;

    private void OnStarted()
    {
        // 自定义启动逻辑
    }

    private void OnStopping()
    {
        // 自定义销毁逻辑
    }
}

在app?.Run()前添加host.Start()后功能正常,但不确定是否为正确实现,同时希望将MyHostedService复用在控制台应用中,捕获WPF与控制台应用的启动/关闭时机。

解决方案

1. 同步启动Host的正确方式

你添加host.Start()的做法是正确的,因为Generic Host必须通过Start()或StartAsync()启动,才能激活所有注册的IHostedService并触发IHostApplicationLifetime的生命周期事件。

需要注意应用退出时要确保Host正常停止,完整的Program.cs代码如下:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;

public class Program
{
    [STAThread]
    public static void Main()
    {
        using var host = Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddSingleton<App>();
                services.AddSingleton<MainWindow>();
                services.AddHostedService<MyHostedService>();
            })
            .Build();

        // 启动Host,激活HostedService并触发生命周期
        host.Start();

        try
        {
            var app = host.Services.GetRequiredService<App>();
            app.Run();
        }
        finally
        {
            // 应用退出时停止Host,触发ApplicationStopping等事件
            host.StopAsync().GetAwaiter().GetResult();
        }
    }
}

2. 更规范的异步启动方案

Generic Host的设计优先支持异步操作,你可以将Main方法改为异步版本(注意保留[STAThread]):

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;

public class Program
{
    [STAThread]
    public static void Main() => MainAsync().GetAwaiter().GetResult();

    private static async Task MainAsync()
    {
        using var host = Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddSingleton<App>();
                services.AddSingleton<MainWindow>();
                services.AddHostedService<MyHostedService>();
            })
            .Build();

        await host.StartAsync();

        try
        {
            var app = host.Services.GetRequiredService<App>();
            // 用Dispatcher等待WPF应用退出
            await app.Dispatcher.InvokeAsync(app.Run);
        }
        finally
        {
            await host.StopAsync();
        }
    }
}

3. 跨应用复用MyHostedService的实现

MyHostedService的设计已经具备跨应用复用的能力,因为它依赖的IHostApplicationLifetime是Generic Host的核心服务,无论是WPF还是控制台应用,只要基于Generic Host构建,都能自动提供该服务。

控制台应用中的复用示例

只需在控制台应用的Host配置中注入MyHostedService即可:

using Microsoft.Extensions.Hosting;

public class ConsoleProgram
{
    public static async Task Main(string[] args)
    {
        using var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices(services =>
            {
                services.AddHostedService<MyHostedService>();
                // 其他控制台服务注册
            })
            .Build();

        await host.RunAsync();
    }
}

控制台应用中host.RunAsync()会自动处理Host的启动和停止,MyHostedService的OnStarted和OnStopping会在对应时机触发。


内容的提问来源于stack exchange,提问作者bairog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:22:46