Fre*_*chs 3 c# async-await windows-runtime storagefile
我想编写一个 Win8 应用程序,在那里我使用一个Configuration带成员的类static,该类在启动时加载一次,并且可以在运行时从任何地方访问。
所以,主要问题是,默认设置存储在xml文件中,但是读取文件内容是异步的(StorageFile),但我没有找到任何解决方案来等待,直到文件完全加载,因为它无法使用await在每种情况下(主线程、构造函数),在我看来都是设计问题。Configuration如果在访问数据之前未完全读取文件,则此应用程序将出现不正确的行为。
这是一个示例代码:
public class Configuration
{
// stores the only instance of this class
private Configuration instance = null;
// public access to the instance
public Configuration Current
{
get
{
if (instance == null)
{
instance = new Configuration();
}
return instance;
}
}
private Configuration()
{
// load data from file synchronously
// so it is loaded once on first access
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定如何解决这个问题,可能我需要改变我的Configuration类的设计。任何建议/提示都会很好。
设计决策不允许任何可能花费超过 50 毫秒的同步调用(即任何文件或网络 IO 调用),以使应用程序响应更快。
尽管您无法await从构造函数进行异步调用,但没有什么可以阻止您在不等待它们完成的情况下触发此类调用:
private Configuration()
{
Init();
}
private async void Init()
{
var contents = await FileIO.ReadTextAsync(file);
}
Run Code Online (Sandbox Code Playgroud)
然后您可以Configuration从内部设置属性Init()。如果您实现INotifyPropertyChanged,您可以在加载值之前将值绑定到 UI,并且 UI 将在加载后刷新。
如果您需要在应用程序中的某个时刻检查或等待操作完成,您可以更改Init()return的签名Task:
private Configuration()
{
InitTask = Init();
}
private async Task Init()
{
var contents = await FileIO.ReadTextAsync(file);
}
public Task InitTask { get; private set; }
Run Code Online (Sandbox Code Playgroud)
现在您可以检查是否已完成:
if (Configuration.Current.IsCompleted)
{
//
}
Run Code Online (Sandbox Code Playgroud)
甚至await它(如果Task已经完成,这将立即完成):
await Configuration.Current.InitTask;
Run Code Online (Sandbox Code Playgroud)
编辑:
如果在加载所述文件之前向用户显示任何内容没有意义,您可以修改您的入口页面以使用替代“视图”:
IsCompleted您可以根据应在已实现的视图模型上公开的属性使正确的可见INotifyPropertyChanged。
然后您可以按如下方式设计页面:
<Page xmlns:common="using:MyApp.Common">
<Page.Resources>
<common:BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</Page.Resources>
<Grid>
<Grid Visibility="{Binding Configuration.IsCompleted, Converter={StaticResource BoolToVisibilityConverter}">
<!-- put your actual view here -->
</Grid>
<Grid Visibility="{Binding Configuration.IsNotCompleted, Converter={StaticResource BoolToVisibilityConverter}">
<!-- put your splash screen view here -->
</Grid>
</Grid>
</Page>
Run Code Online (Sandbox Code Playgroud)