c# - Windows Metro 异步加载数据

标签 c# microsoft-metro windows-runtime .net-4.5 async-await

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

    public MyDataSource()
    {
        DataLoaded = false;

        LoadData();
    }

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;
    }

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

编辑:

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

if (!DataLoaded)
{
    //dataLoading = await MyDataSource.LoadData();
    dataLoading.RunSynchronously();
}

但这给了我一个错误:

RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.

dataLoading.Wait()

只是锁定 UI。

最佳答案

我认为这听起来是最好的选择,如果您将构造函数设为 async。但是自 that's not possible 以来,您可以做的是为 MyDataSource 创建一个 async 工厂方法:

private MyDataSource()
{
    DataLoaded = false;
}

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

然后使用await初始化_myDataSource:

_myDataSource = await MyDataSource.Create();

如果由于某种原因,您不能这样做,您可以存储工厂方法返回的 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;
}

关于c# - Windows Metro 异步加载数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11547251/

相关文章:

c# - 将图像与文本一起添加到 ListView (Metro App)

windows-8 - WebView 的自定义用户代理

xaml - 何时在 UserControl 上使用模板化控件?

c# - 如何以编程方式关闭消息对话框

c# - 同步调用Async, 'marshalled for a different thread'消息

c# - 如何通过 C# 中的代码递增字母数字 ID

c# - 设计器中的字体与运行时的字体大小不同

c# - ASP .NET 一对一关系 CRUD

node.js - 如何以编程方式启动/停止 Metro Bundler

c# - 为什么我不能将不可打印的字符定义为常量 c#