在Windows Universal 8.1上使用async方法

时间:2015-09-20 11:16:26

标签: c# windows-phone-8.1 windows-8.1

我有一个页面(主页)和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获取数据,因此我的应用程序出错。
我该如何解决?有可能帮助我吗? 感谢。

2 个答案:

答案 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 = ...
    }
}

}