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.
我认为这听起来像是最好的选择,如果你做了构造函数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)