.NET 通用主机 - 是否可以停止并重新启动主机?

.NET Generic Host - Is it possible to stop and restart a host?

考虑这个没有特殊配置或托管服务的极其简单的 .NET Core 3.1(和 .NET 5)应用程序:

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

internal class Program
{
    public static async Task Main(string[] args)
    {
        var builder = Host.CreateDefaultBuilder(args);
        builder.UseWindowsService();
        var host = builder.Build();

        var fireAndforget = Task.Run(async () => await host.RunAsync());
        await Task.Delay(5000);
        await host.StopAsync();
        await Task.Delay(5000);
        await host.RunAsync();
    }

第一个 运行(仅出于本次测试的目的作为后台触发和忘记任务发送)和停止成功完成。第二次调用 运行 时,我收到此异常:

System.AggregateException : 'Object name: 'EventLogInternal'.Cannot access a disposed object. Object name: 'EventLogInternal'.)'

如果我这样做但使用 StartAsync 而不是 运行Async(这次不需要 fireAndForget),我会在第二次调用 StartAsync 时收到 System.OperationCanceledException

我推断 .NET Generic Host 不应该停止和重新启动是否正确?

为什么我需要这个?

我的目标是将单个应用程序 运行 作为 Windows 服务来托管两个不同的 .NET 通用主机。这是基于 here 的建议,以便具有单独的配置和依赖项注入规则和消息队列。

一个将在整个应用程序生命周期内保持活动状态(直到服务在 Windows 服务中停止)并将作为接收消息事件的入口点,该消息事件将 start/stop 另一个将是提供完整服务的主要处理主机。这样,主要服务可以处于“空闲”状态,直到它们收到触发其进程的消息,而另一条消息可以 return 它们进入空闲状态。

CreateDefaultBuilder(...).Build() 返回的主机代表整个应用程序。来自 docs:

The main reason for including all of the app's interdependent resources in one object is lifetime management: control over app startup and graceful shutdown.

默认构建器在单例范围内注册许多服务,当主机停止时,所有这些服务都将被处理或切换到某种“停止”状态。例如,在调用 StopAsync 之前,您可以解析 IHostApplicationLifetime:

var appLifetime = host.Services.GetService<IHostApplicationLifetime>();

它有代表应用程序状态的取消标记。当您在停止后调用 StartAsync 或 RunAsync 时,所有标记仍将 IsCancellationRequested 设置为 true。这就是 OperactionCancelledExceptionHost.StartAsync.

中被抛出的原因

您可以在配置期间列出其他服务:

对我来说,听起来您只需要一些后台作业来处理消息,但我从未使用过 NServiceBus,所以我不知道它如何与 Hangfire 之类的东西一起工作。您还可以实施 IHostedService 并在通用主机构建器中使用它。

我正在做类似的事情:

do
{
    using IHost host = BuildHost();
    await host.RunAsync();
} while (MainService.Restart);

使用 MainService 构造函数:

public MainService(IHostApplicationLifetime HostApplicationLifetime)

MainService.Restart 是由 MainService 本身设置的静态布尔值,以响应也调用 HostApplicationLifetime.StopApplication().

的某些事件