AvaloniaUI странная асинхронная загрузка приложенияC#

Место общения программистов C#
Ответить
Anonymous
 AvaloniaUI странная асинхронная загрузка приложения

Сообщение Anonymous »

Запуск моего приложения AvaloniaUI выглядит следующим образом:

Код: Выделить всё

try
{
var provider = Services;
var logger = provider.GetRequiredService();
logger.Information("Initializing GMenu...");
//await LoadMaterialThemeAsync(provider);
await LoadLocalizationAsync(provider).ConfigureAwait(false);

logger.Information("Desktop files paths: {paths}", StaticConfiguration.PathToDesktopFiles);
logger.Information("Desktop files icons path: {paths}", StaticConfiguration.PathsToRefineIcon);

if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainWindow { DataContext = Services.GetRequiredService() };

await LoadConfigurationAsync(provider).ConfigureAwait(false);

base.OnFrameworkInitializationCompleted();
}
catch (Exception e)
{
Services.GetRequiredService().Error(e, "An error occurred while initializing the application.");
Console.WriteLine(e);
Environment.Exit(-1);
}

Код: Выделить всё

LoadLocalizationAsync
просто запускает службу, которая читает файл .json с локализацией (я не могу использовать .resx, потому что они не совместимы с Native AOT), если я удалю ConfigurationAwait(false, MainWindow не будет отображаться, но метод продолжит выполнение (поскольку из журналов я вижу, что конфигурация начинает загружаться).
Этот код был изменен на 60%, чтобы завершиться сбоем исключение:

Код: Выделить всё

[ERR] [2026-04-28 20:50] [13] An error occured while initializing the application.
System.InvalidOperationException: Call from invalid thread
at Avalonia.Threading.Dispatcher.g__ThrowVerifyAccess|16_0()
at Avalonia.Threading.Dispatcher.VerifyAccess()
at Avalonia.Platform.ScreensBase`2.EnsureScreens()
at Avalonia.Platform.ScreensBase`2.get_AllScreens()
at Avalonia.X11.X11Window..ctor(AvaloniaX11Platform platform, IWindowImpl popupParent, X11WindowMode mode, Boolean overrideRedirect)
at Avalonia.X11.X11Window..ctor(AvaloniaX11Platform platform, IWindowImpl popupParent, Boolean overrideRedirect)
at Avalonia.X11.AvaloniaX11Platform.CreateWindow()
at Avalonia.Controls.Platform.PlatformManager.CreateWindow()
at Avalonia.Controls.Window..ctor()
at ReactiveUI.Avalonia.ReactiveWindow`1..ctor() in /_/src/ReactiveUI.Avalonia/ReactiveWindow.cs:line 34
at GMenu.Views.MainWindow..ctor() in /home/themakarik/RiderProjects/g-menu/src/GMenu/Views/MainWindow.axaml.cs:line 7
at GMenu.App.OnFrameworkInitializationCompleted() in /home/themakarik/RiderProjects/g-menu/src/GMenu/App.axaml.cs:line 31
System.InvalidOperationException: Call from invalid thread
at Avalonia.Threading.Dispatcher.g__ThrowVerifyAccess|16_0()
at Avalonia.Threading.Dispatcher.VerifyAccess()
at Avalonia.Platform.ScreensBase`2.EnsureScreens()
at Avalonia.Platform.ScreensBase`2.get_AllScreens()
at Avalonia.X11.X11Window..ctor(AvaloniaX11Platform platform, IWindowImpl popupParent, X11WindowMode mode, Boolean overrideRedirect)
at Avalonia.X11.X11Window..ctor(AvaloniaX11Platform platform, IWindowImpl popupParent, Boolean overrideRedirect)
at Avalonia.X11.AvaloniaX11Platform.CreateWindow()
at Avalonia.Controls.Platform.PlatformManager.CreateWindow()
at Avalonia.Controls.Window..ctor()
at ReactiveUI.Avalonia.ReactiveWindow`1..ctor() in /_/src/ReactiveUI.Avalonia/ReactiveWindow.cs:line 34
at GMenu.Views.MainWindow..ctor() in /home/themakarik/RiderProjects/g-menu/src/GMenu/Views/MainWindow.axaml.cs:line 7
at GMenu.App.OnFrameworkInitializationCompleted() in /home/themakarik/RiderProjects/g-menu/src/GMenu/App.axaml.cs:line 31
Это нормально, потому что этот метод продолжает выполняться в другом потоке (не в потоке пользовательского интерфейса), но если я попытаюсь создать MainWindow из диспетчера:

Код: Выделить всё

var provider = Services;
var logger = provider.GetRequiredService();
logger.Information("Initializing GMenu...");
//await LoadMaterialThemeAsync(provider);
await LoadLocalizationAsync(provider).ConfigureAwait(false);

logger.Information("Desktop files paths: {paths}", StaticConfiguration.PathToDesktopFiles);
logger.Information("Desktop files icons path: {paths}", StaticConfiguration.PathsToRefineIcon);

Dispatcher.UIThread.Invoke(() =>
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainWindow { DataContext = Services.GetRequiredService() };
});

await LoadConfigurationAsync(provider).ConfigureAwait(false);

base.OnFrameworkInitializationCompleted();

Код: Выделить всё

MainWindow
снова не отображается, но что более интересно: моя старая версия загрузки приложения с шаблонным журналированием работает правильно (пока я не удалю ConfigurationAwait(false), MainWindow не будет отображаться как всегда):

Код: Выделить всё

try
{
var provider = Services;
provider.GetRequiredService().Information("Initializing GMenu...");
//await LoadMaterialThemeAsync(provider);
await LoadLocalizationAsync(provider).ConfigureAwait(false);
provider.GetRequiredService().Information("Desktop files paths: {paths}", StaticConfiguration.PathToDesktopFiles);
provider.GetRequiredService().Information("Desktop files icons path:  {paths}", StaticConfiguration.PathsToRefineIcon);

if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainWindow { DataContext = Services.GetRequiredService() };

await LoadConfigurationAsync(provider).ConfigureAwait(false);

base.OnFrameworkInitializationCompleted();
}
Я не знаю, как эти вещи связаны, может кто-нибудь объяснить мне и как я могу исправить свой код, чтобы он снова работал (я не могу переместить загрузку конфигурации вниз, потому что она должна загружаться после отображения окна, иначе содержимое окна не будет локализовано).
>
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»