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

标签 c# android xamarin.forms uwp async-await

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

问题来了。我正在尝试根据当前应用程序状态将我的应用程序加载到特定页面。确定应用程序的状态。它包括扫描到数据文件夹。为了在 UWP 中使用 Storage API。我必须在 Xamarin Forms 中创建一个 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);
    }
}

应用程序启动时,需要先从数据文件夹中加载JobList。然后查看 JobList 并确定要导航到的页面。

我目前正在尝试做的是从 App 类的构造函数中调用下面的代码。

App.xaml.cs

InitializeComponent(); // Default

var appManager = AppManager.Instance;
appManager .InitializeAsync();
if(appManager .JobExists("JobA")){
    MainPage = new PageA();
}else{
    MainPage = new PageB();
}

这将始终将我带到 PageB,因为列表是空的,因为初始化尚未完成。这是由于在 synchronous 线程中运行 async 代码引起的。

我在 this blog 中阅读了多种制作异步构造函数的方法。 .但是,他们仍然要求我在调用中创建一个 await 函数,这在这种情况下是不可能的。

我还尝试将整个 App() 构造函数代码移动到 async Task 函数中,然后调用 InitializeAsync().Wait()在构造函数中。但是,Xamarin Forms 会在运行时提示。因为 AppMainPage 上有 null 引用。

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

最佳答案

问题是 Xamarin.Forms 期望 MainPage 在初始化后立即设置。如果使用 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.Forms 初始化之前的 OnLaunched 方法重写中:

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

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

    ...
}

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

您拥有的最终选项在 this blog post 中有所描述。亚当佩德利。它允许您在 UI 线程上运行任务,但会阻塞直到使用 TaskHelper library 完成任务。 .

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

这可能应该是最后一个选项,因为它可以被认为是一种 hack,而不是一个正确的解决方案。

关于c# - 初始化 Xamarin.Forms 应用程序时找不到调用异步方法的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49915959/

相关文章:

c# - 如何获取请求的默认文档?

c# - 如何在特定时区创建 DateTime 的新实例?

c# - iCalendar 不为组织者创建事件

android - 如何获取 "push"fragment ?

android - 为什么我对 Canvas.drawText() 的调用不起作用

xamarin - 如果未在使用模板的 XAML 中指定,我怎样才能使模板内的 HeightRequest 被忽略?

c# - System.DllNotFoundException :/system/lib/libsqlite. 所以

Azure 应用服务 - Google 帐户 ID 不匹配

c# - 何时同时运行异步函数?

android - 在 Gradle 中加载 Material - 下载失败 'android-P'