我有一个页面(主页)和SQLite数据库。我需要首先reed SQLite数据库,然后更新我的页面控件 这是我的页面代码:
public MainPage()
{
this.InitializeComponent();
// Get SQLite and language setting
SQLiteData();
// Update controls in page
GetConnectionList();
}
这是SQLiteData()的代码:
public async void SQLiteData()
{
conn = new SQLiteAsyncConnection("Setting.db");
await conn.CreateTableAsync<SettingTable>();
await conn.CreateTableAsync<DataPlanTable>();
....
}
因为我使用等待&#39;在SQLiteData()中,调试器运行GetConnectionList()而不完成并从SQLite获取数据,因此我的应用程序出错。
我该如何解决?有可能帮助我吗?
感谢。
答案 0 :(得分:1)
关键是您将SQLiteData声明为异步,但在您的MainPage构造函数中,您还没有等待&#39;用于完成SQLiteData任务。
你应该等待SQLiteData完成,但你不能在构造函数内轻松地做到这一点......你也不应该这样做。 Can constructors be async?
请将耗时和异步任务从构造函数中移出到类中的其他方法中,一个关键原因是您可以实现一些更好的错误处理例程,如果连接失败,您可以重新执行连接逻辑第一次。
public async InitialiseDataConnections()
{
// Get SQLite and language setting
await SQLiteData();
// Update controls in page
GetConnectionList();
}
现在你有可以从构造函数中调用的单一用途方法......但更好的解决方案是从页面类的OnNavigatedTo事件处理程序调用它。
编程中的一般期望是,与针对对象的动作的执行相比,创建对象的实例应该相对轻量级。这是一个有趣的讨论:How much work should be done in a constructor
在通用应用程序中,期望轻量级配置在构造函数中处理,并且大部分初始化&#39;逻辑&#39;延迟,直到页面实际导航到(OnNavigatedTo)。特别是当我们考虑数据访问场景时,数据尽可能保持最新可能很重要,但还有另一个重要事件,即导航到页面导致后向导航或应用程序恢复后。在这些事件中,您可以从先前的序列化状态获取某些状态或配置,而不是重新初始化所有可能是一个耗时过程的过程。
所以&#39;最佳做法&#39;这里是使用OnNavigatedTo来处理除页面控件创建之外的任何页面初始化。您可以访问NavigationEventArgs,它将帮助您在用户期望的状态下重新创建页面。其他开发人员首先会查看页面背后的业务逻辑, AND 您可以将OnNavigatedTo处理程序声明为异步!
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await InitialiseDataConnections();
}
答案 1 :(得分:0)
执行此操作的一种方法是在OnNavigatedTo中将异步初始化移出ctor。但是,您必须意识到OnNavigatedTo将在其异步部分完成之前将控制权返回给框架。这可能没问题,但你需要考虑如何处理错误。
我会以不同的方式构建这段代码:
...
// The UI will use data binding to PageState to show
// UI specific for the initialization phase.
public PageState PageState {get; private set {.../*include property change notification */...};}
// The UI will use data binding to ErrorMessage as needed.
public string ErrorMessage {get; private set {.../*include property change notification */...};}
...
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await InitializeAsync();
}
private async Task InitializeAsync()
{
try
{
// Have the UI bind to
PageState = PageState.InitializingInProgress;
await SQLiteData();
GetConnectionList();
...
PageState = PageState.InitializedOk;
}
catch(...)
{
PageState = PageState.InitializedWithError;
ErrorMessage = ...
}
}
}