通用窗口,c#,在应用程序初始化期间等待

本文关键字:初始化 等待 应用程序 窗口 | 更新日期: 2023-09-27 18:13:24

我正在尝试将我在Windows Phone 8上运行的一款简单应用移植到Universal Windows上。在构建主框架/页面之前,我需要加载(本地)几个文件,因为这些文件指示如何首先创建页面。有一个。xml和一些内容文件是资产的一部分。

我曾经在App.Application_Launching()期间进行初始化,我猜现在被app . onlaunching()所取代。问题是新的异步文件IO,我似乎找不到一个地方,我可以调用任何异步api而不会挂起程序。似乎在app . onlaunching (), MainPage.MainPage(), MainPage.OnNavigatedTo()等任何地方。我不能使用await

我基本上必须启动一个后台线程来安排一个任务稍后运行,以进行实际的初始化,然后回调到MainPage的池中以使某些东西正确运行。生成的代码如下所示。似乎过于复杂,但我想这是正确的?

谢谢,尼克。

public partial class MainPage : Page
{
    // Constructor
    public MainPage()
    {
        InitializeComponent();
        // This doesn't work ...
        // var task = InitAsync();
        // task.Wait()

        // This seems to ...
        IAsyncAction asyncAction = ThreadPool.RunAsync((workItem) =>
        {
            var ignored = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                TryInitAsync();
            });
        });
    }
    private async void TryInitAsync()
    {
        try
        {
            await InitAsync();
        }
        catch
        {
            int foo = 0;
        }
    }
    private async Task<Boolean> InitAsync()
    {
        // Things that go await in the night
        // Other things that update the layout
        return true;
    }
}

通用窗口,c#,在应用程序初始化期间等待

似乎过于复杂,但我想这是正确的?

不,我不这么认为。

我不能提供关于初始化本身的具体建议,因为你的问题中缺少这些细节。基本策略是让UI容忍未初始化的数据,并异步运行初始化,根据需要更新属性。

就您启动异步初始化的具体方法而言,您已经使它比需要或应该的更复杂。这样会更好:

public MainPage()
{
    InitializeComponent();
    var ignored = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow
        .Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => TryInitAsync());
}

。没有必要启动ThreadPool.RunAsync()的后台任务,如果你要做的是推迟对TryInitAsync()方法的调用,在UI线程上调用它。

这样做(或者你更复杂的方式),你仍然阻塞UI线程。使用Dispatcher.RunAsync()会更好。相反,直接从后台任务调用TryInitAsync()(例如,用ThreadPool.RunAsync()调用它),并使ui绑定属性依赖于初始化,随着初始化的进行异步更新。

似乎在app . onlaunching (), MainPage.MainPage(), MainPage.OnNavigatedTo()等任何地方。我不能使用await

核心概念变化是现代应用程序必须立即显示某种UI (这意味着同步)。这就是为什么你不能在启动时做I/O。 所以,在加载任何文件之前,你必须考虑你的应用应该是什么样子,立即显示这个状态,并且开始异步加载你的"真实"UI。

你可以直接从构造函数中调用TryInitAsync:

public MainPage()
{
  InitializeComponent();
  TryInitAsync();
}

或者,如果你能用数据绑定更新你的UI,你可以使用我的NotifyTask<T>类型:

public NotifyTask<InitData> Data { get; }
public MainPage()
{
  InitializeComponent();
  Data = NotifyTask.Create(InitAsync());
}
private async Task<InitData> InitAsync() { ... }

然后你可以数据绑定到Data.Result来获得InitData,或者Data.IsCompleted/Data.IsNotCompleted来显示/隐藏初始的"loading…"状态