在Windows Universal 8.1上使用async方法
本文关键字:async 方法 Windows Universal | 更新日期: 2023-09-27 18:13:49
我有一个页面(Mainpage)和SQLite数据库。我需要首先需要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>();
....
}
因为我在SQLiteData()中使用'await',调试器去运行GetConnectionList()而没有完成并从SQLite获取数据,所以我在我的应用程序中得到错误。
怎么解呢?有可能帮助我吗?
谢谢。
关键是您声明SQLiteData为异步,但在您的MainPage构造函数中,您没有'等待' SQLiteData任务完成。
你应该等待SQLiteData完成,但你不能在构造函数中轻易做到这一点…你也不应该这样。构造函数可以异步吗?
请将耗时的异步任务从构造函数中移出,放到类中的其他方法中,一个关键原因是这样你就可以实现一些更好的错误处理例程,如果第一次连接失败,你可以重新执行连接逻辑。
public async InitialiseDataConnections()
{
// Get SQLite and language setting
await SQLiteData();
// Update controls in page
GetConnectionList();
}
现在你有一个单一用途的方法,你可以从构造函数调用…但是一个更好的解决方案是在你的页面类的OnNavigatedTo事件处理程序中调用它。
在编程中,一般期望创建对象的实例相对于对对象执行操作来说应该是相对轻量级的。这里有一个有趣的讨论:构造函数
中应该完成多少工作?在通用应用程序中,轻量配置是在构造函数中处理的,初始化"逻辑"的大部分被延迟到页面实际导航到(OnNavigatedTo)。特别是当我们考虑数据访问场景时,让数据尽可能保持最新可能很重要,但还有另一个重要事件,当页面导航导致向后导航或应用程序恢复之后。在这些事件中,你可以从之前的序列化状态中获得一些状态或配置,而不是重新初始化所有的东西,这可能是一个耗时的过程。
所以这里的"最佳实践"是使用OnNavigatedTo来处理任何页面初始化,而不是创建页面控件。你可以访问NavigationEventArgs,它将帮助你以用户期望的状态重新创建页面。这是其他开发人员首先查看页面背后的业务逻辑的地方,和您可以将OnNavigatedTo处理程序声明为async!
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await InitialiseDataConnections();
}
这样做的一种方法是将异步初始化移出OnNavigatedTo中的actor。但是,您必须意识到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 = ...
}
}
}