Windows Metro异步加载数据

Pau*_*els 2 c# async-await microsoft-metro windows-runtime .net-4.5

我已经基于Split Page示例应用程序创建了一个Windows 8 Metro应用程序.但是,在示例应用程序中,数据在构造函数中同步加载.我正在访问文本文件,因此需要异步加载数据.构造函数如下所示:

    public MyDataSource()
    {
        DataLoaded = false;

        LoadData();
    }
Run Code Online (Sandbox Code Playgroud)

LoadData()是一种填充数据模型的异步方法.这工作正常,并在加载数据时显示数据(这是我想要的行为).当我尝试测试挂起并终止时,会出现问题.问题是恢复有可能在填充之前尝试访问数据模型:

    public static MyDataGroup GetGroup(string uniqueId)
    {
        // If the data hasn't been loaded yet then what?
        if (_myDataSource == null)
        {
        // Where app has been suspended and terminated there is no data available yet
        }

        // Simple linear search is acceptable for small data sets
        var matches = _myDataSource.AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
        if (matches.Count() == 1) return matches.First();
        return null;
    }
Run Code Online (Sandbox Code Playgroud)

我可以通过更改要调用的构造函数来解决此问题LoadData().Wait,但这意味着应用程序会锁定UI线程.我认为我需要的是一种获取恢复代码的方法,GetGroup以等待数据加载而不锁定UI线程.这是可行的还是可取的,如果是这样,怎么样?

编辑:

有一两个人建议缓存任务LoadData().这是一个很好的主意,但内部代码GetGroup由页面状态管理部分调用,因此不能是异步的.为了解决这个问题,我尝试了以下方法:

if (!DataLoaded)
{
    //dataLoading = await MyDataSource.LoadData();
    dataLoading.RunSynchronously();
}
Run Code Online (Sandbox Code Playgroud)

但这给了我一个错误:

RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
Run Code Online (Sandbox Code Playgroud)

dataLoading.Wait()
Run Code Online (Sandbox Code Playgroud)

只是锁定UI.

svi*_*ick 5

我认为这听起来像是最好的选择,如果你做了构造函数async.但由于这是不可能的,你可以做的是创建一个async工厂方法MyDataSource:

private MyDataSource()
{
    DataLoaded = false;
}

public static async Task<MyDataSource> Create()
{
    var source = new MyDataSource();
    await source.LoadData();
    return source;
}
Run Code Online (Sandbox Code Playgroud)

然后初始化_myDataSource使用await:

_myDataSource = await MyDataSource.Create();
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因,您无法执行此操作,则可以存储Task由工厂方法返回的内容并在GetGroup()以下位置等待:

_myDataSourceTask = MyDataSource.Create();

…

public static async Task<MyDataGroup> GetGroup(string uniqueId)
{
    var myDataSource = await _myDataSourceTask;

    // Simple linear search is acceptable for small data sets
    var matches = myDataSource.AllGroups.Where(group => group.UniqueId == uniqueId);
    if (matches.Count() == 1) return matches.First();
    return null;
}
Run Code Online (Sandbox Code Playgroud)