C# 初始化Xamarin.Forms应用程序时找不到调用异步方法的方法

C# 初始化Xamarin.Forms应用程序时找不到调用异步方法的方法,c#,android,xamarin.forms,uwp,async-await,C#,Android,Xamarin.forms,Uwp,Async Await,异步/等待线程在这里让我抓狂。我对异步初始化的可能性做了很多研究 问题就在这里。我正在尝试根据当前应用程序状态将我的应用程序加载到特定页面。以确定应用程序的状态。它包括扫描数据文件夹。为了在UWP中使用存储API。我必须在Xamarin表单中创建一个async依赖项服务 我在这里使用一个带有AppManager类的单例模式 AppManager.cs public class AppManager{ public static AppManager Instance = new AppM

异步/等待线程在这里让我抓狂。我对异步初始化的可能性做了很多研究

问题就在这里。我正在尝试根据当前应用程序状态将我的应用程序加载到特定页面。以确定应用程序的状态。它包括扫描数据文件夹。为了在UWP中使用
存储API
。我必须在Xamarin表单中创建一个
async
依赖项服务

我在这里使用一个带有
AppManager
类的单例模式

AppManager.cs

public class AppManager{
    public static AppManager Instance = new AppManager();
    public List<Jobs> JobList = new List<Jobs>();

    public async Task InitializeAsync(){
        JobList.AddRange(await DependencyService.Get<IFileService>().GetJobs());
    }

    public bool JobExists(string jobName){
        return JobList.Any(j => j.Name == jobName);
    }
}
由于初始化未完成,因此列表为空,因此我将始终转到
PageB
。这是由于在
synchronous
线程中运行
async
代码造成的

我读过关于在中创建异步构造函数的多种方法。但是,它们仍然要求我在调用中执行
wait
函数,这在本例中是不可能的

我还尝试将整个
App()
构造函数代码移动到
async Task
函数中,然后在构造函数中调用
InitializeAsync().Wait()
。然而,Xamarin表单在运行时会抱怨。由于
App
MainPage
上有
null
引用


我想知道是否有可能在不涉及不良实践(例如async void)的情况下使用等待的函数实现完全初始化?我还知道如何应对这种情况,例如使用
SystemIO
而不是
Storage API
仍然适用于Xamarin Forms UWP。但我真的很想深入研究
async
函数,而不仅仅是让它工作。谢谢。

问题是Xamarin.Forms希望
主页在初始化后立即设置。如果使用
async
调用,则需要等待调用完成,这将不可避免地导致XF抱怨缺少页面

这个问题有三种解决方案

您可以在启动时显示临时“加载页面”。在这种情况下,您首先将
MainPage
设置为通知用户应用正在加载的页面:

public App()
{
   MainPage = new LoadingPage();
}
然后在
OnStart
覆盖中继续执行
async
操作:

protected override async void OnStart()
{
   var appManager = AppManager.Instance;
   await appManager.InitializeAsync();
   if(appManager .JobExists("JobA"))
   {
      MainPage = new PageA();
   }
   else
   {
      MainPage = new PageB();
   }
}
第二个选项是在初始化Xamarin.Forms之前连接异步初始化任务。对于UWP,您可以转到UWP项目的
App.xaml.cs
文件,并将其放在Xamarin初始化之前的
OnLaunched
方法覆盖中:

protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
    ...

    var appManager = AppManager.Instance;
    await appManager.InitializeAsync();
    Xamarin.Forms.Forms.Init(e);

    ...
}
这只会延长基于UWP的启动屏幕,但在初始化Xamarin.Forms时,
AppManager
将已经初始化

Adam Pedley在中描述了您的最终选择。它允许您在UI线程上运行任务,但会一直阻止,直到任务使用


这可能是最后一种选择,因为它可以被视为一种黑客行为,而不是一种合适的解决方案。

将异步内容移动到应用程序生命周期事件之一而不是构造函数是合乎逻辑的。在构造函数中有这样的登录不是最佳实践。
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
    ...

    var appManager = AppManager.Instance;
    await appManager.InitializeAsync();
    Xamarin.Forms.Forms.Init(e);

    ...
}
Exrin.Common.ThreadHelper.Init(SynchronizationContext.Current);
Exrin.Common.ThreadHelper.RunOnUIThread(async () => { await MyMethod(); });