![](/img/trans.png)
[英]What event can be used to detect when WinUI3 TeachingTip has opened or loaded
[英]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.