簡體   English   中英

為什么 .NET 通用主機與 WinUI3 一起使用時不會停止?

[英]Why doesn't the .NET Generic Host stop when used with WinUI3?

我正在使用 .NET 5 編寫一個 WinUI3 (Project Reunion 0.5) 應用程序,並且想使用 .NET 通用主機。 我正在使用帶有自定義IHostedService的默認主機:

public App() {
    _host = Host.CreateDefaultBuilder()
        .ConfigureServices((context, services) =>
        {
            services.AddHostedService<MyHostedService>();
        }).Build();
    InitializeComponent();
}

托管服務在StopAsync中執行一些異步操作。 出於演示目的,假設它延遲 1 秒(此代碼仍然會產生問題):

public override async Task StopAsync(CancellationToken cancellationToken)
{
    await Task.Delay(1000);
}

我在OnLaunched中啟動主機:

protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    await _host.StartAsync();
    m_window = new MainWindow();
    m_window.Activate();
}

我讓默認的ConsoleLifetime實現在進程退出之前停止主機。

我的IHostedService.StopAsync實現返回的Task完成,但IHost.StopAsync永遠不會返回,並且進程掛起並在 output 中顯示此消息:

Microsoft.Hosting.Lifetime: Information: Application is shutting down...
Microsoft.Hosting.Lifetime: Information: Waiting for the host to be disposed. Ensure all 'IHost' instances are wrapped in 'using' blocks.

如果我使用調試器單步執行,有時IHost.StopAsync方法會超時並引發異常。 這永遠不會在調試器之外發生。 我嘗試在MainWindow關閉時明確停止和處置主機,但沒有任何區別。

我想也許DispatcherQueueSynchronizationContext在主機停止並且任務沒有得到服務之前被關閉,但是DispatcherQueue.ShutdownStarting事件從未被觸發。

還有其他想法嗎?

我從評論中聽取了@Dai 的建議,並調查了在單獨的線程上運行 WinUI 並在主線程上運行主機。

我創建了一個IHostedService來管理 WinUI 應用程序:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.System;
using Microsoft.UI.Xaml;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace MyApp.Hosting
{

public class WinUIHostedService<TApplication> : IHostedService, IDisposable
    where TApplication : Application, new()
{
    private readonly IHostApplicationLifetime HostApplicationLifetime;
    private readonly IServiceProvider ServiceProvider;

    public WinUIHostedService(
        IHostApplicationLifetime hostApplicationLifetime,
        IServiceProvider serviceProvider)
    {
        HostApplicationLifetime = hostApplicationLifetime;
        ServiceProvider = serviceProvider;
    }

    public void Dispose()
    {
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        var thread = new Thread(Main);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    private void Main()
    {
        WinRT.ComWrappersSupport.InitializeComWrappers();
        Application.Start((p) => {
            var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread());
            SynchronizationContext.SetSynchronizationContext(context);
            new TApplication();
        });
        HostApplicationLifetime.StopApplication();
    }
}

}

我在構建設置中定義了DISABLE_XAML_GENERATED_MAIN並添加了我自己的Main

public class Program
{
    public static void Main(string[] args)
    {
        Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddHostedService<WinUIHostedService<App>>();
            })
            .Build().Run();
    }
}

瞧,當主 window 關閉時,WinUI 應用程序仍然運行良好,並且主機干凈地停止,即使IHostedService.StopAsync運行異步代碼也是如此。

請注意,此代碼只是第一個起作用的代碼。 它可能會得到改進,我不完全理解通用主機生命周期語義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM