异步/等待线程在这里让我发疯。我对异步初始化的可能性做了很多研究。
这是问题所在。我正在尝试根据当前应用程序状态将我的应用程序加载到特定页面。确定应用程序的状态。它包括扫描到数据文件夹。为了Storage API
在 UWP 中使用。我必须async
在 Xamarin Forms 中创建一个依赖服务。
我在这里使用带有AppManager
类的单例模式。
应用程序管理器
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
类的构造函数调用下面的代码。
应用程序.xaml.cs
InitializeComponent(); // Default
var appManager = AppManager.Instance;
appManager .InitializeAsync();
if(appManager .JobExists("JobA")){
MainPage = new PageA();
}else{
MainPage = new PageB();
}
这将始终让我进入,PageB
因为列表是空的,因为初始化尚未完成。这是由async
在synchronous
线程中运行代码引起的。
我已在此博客中阅读了多种制作异步构造函数的方法。但是,他们仍然要求我await
在调用中创建一个函数,这在这种情况下是不可能的。
我还尝试将整个App()
构造函数代码移动到一个async Task
函数中,然后InitializeAsync().Wait()
在构造函数中调用。但是,Xamarin Forms 会在运行时抱怨。如App
由具有null
对参考MainPage
。
我想知道是否有可能在不涉及不良做法(例如异步无效)的情况下使用等待的函数实现完全初始化?我也有一些关于如何解决这种情况的想法,例如使用SystemIO
而不是Storage API
仍然适用于 Xamarin Forms UWP。但我真的很想深入了解async
功能,而不仅仅是让它发挥作用。谢谢。
问题是 Xamarin.Forms 期望在MainPage
初始化后立即设置。如果你使用async
call,你需要等待它完成,这将不可避免地导致XF抱怨缺少页面。
这个问题有三种解决方案。
您可以在启动时显示一个临时的“加载页面”。在这种情况下,您首先设置MainPage
一个页面,通知用户该应用程序正在加载:
public App()
{
MainPage = new LoadingPage();
}
然后继续执行覆盖中的async
操作OnStart
:
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
文件并将其放在OnLaunched
Xamarin.Forms 初始化之前的方法覆盖中:
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 线程上运行任务,但会阻塞,直到使用TaskHelper
库完成任务。
Exrin.Common.ThreadHelper.Init(SynchronizationContext.Current);
Exrin.Common.ThreadHelper.RunOnUIThread(async () => { await MyMethod(); });
这可能应该是最后的选择,因为它可以被视为一种黑客攻击,而不是一个适当的解决方案。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句