【发布时间】:2012-07-18 17:42:44
【问题描述】:
我创建了一个基于拆分页面示例应用程序的 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。
【问题讨论】:
-
为什么不在另一个线程中启动 LoadData() 呢?我不知道
LoadData()是否是自定义方法,如果您编写了它的代码,我高度怀疑这就是问题所在。 -
在调用 LoadData 之前设置一个布尔值; IsLoading = true;当异步加载完成时设置 IsLoading = false;在你 GetGroup 检查 IsLoading == true;如果是这样,请等待。
-
@Blam - 这是我的想法。但是如何在不锁定 UI 线程的情况下等待呢?
-
@pm_2:如果您可以获取/存储可等待对象,那么您可以让 await 为您执行此操作。它让 GetGroup 的代码无论加载是否完成都可以工作
-
与您的问题无关,但是如果您找到多个匹配项,您真的要返回
null吗?我认为例外会更有意义,在这种情况下,您可以使用SingleOrDefault()来简化代码。
标签: c# microsoft-metro windows-runtime .net-4.5 async-await