C# Windows RT-StorageFile的同步使用
我想写一个Win8应用程序,在那里我使用一个C# Windows RT-StorageFile的同步使用,c#,windows-runtime,async-await,storagefile,C#,Windows Runtime,Async Await,Storagefile,我想写一个Win8应用程序,在那里我使用一个配置-类和一个静态成员,它在启动时加载一次,在运行时可以从任何地方访问 因此,主要问题是,默认设置存储在xml文件中,但读取文件内容是异步的(StorageFile),但我没有找到任何解决方案来等待,直到文件完全加载,因为不可能在任何情况下(主线程、构造函数)都使用wait,在我看来,这是一个设计问题。 如果在访问配置数据之前未完全读取文件,则此应用程序将出现错误行为 下面是一个示例代码: public class Configuration {
配置
-类和一个静态
成员,它在启动时加载一次,在运行时可以从任何地方访问
因此,主要问题是,默认设置存储在xml文件中,但读取文件内容是异步的(StorageFile
),但我没有找到任何解决方案来等待,直到文件完全加载,因为不可能在任何情况下(主线程、构造函数)都使用wait
,在我看来,这是一个设计问题。
如果在访问配置
数据之前未完全读取文件,则此应用程序将出现错误行为
下面是一个示例代码:
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
}
}
我不确定如何解决这个问题,可能我需要更改
配置
-类的设计。任何建议/提示都很好。您不需要另一个类来存储设置-为每个Windows 8应用程序提供了应用数据.Current.LocalSettings
字典,该字典在每次启动应用程序时自动加载,您阅读时不使用wait
关键字-例如:
var settings = ApplicationData.Current.LocalSettings;
settings.Values["MyIndex"] = 2;
object value = settings.Values["MyIndex"];
if (value != null)
{
int myIndex = (int)value;
//...
}
这是一项设计决策,不允许任何可能需要超过50毫秒的同步调用,即任何文件或网络IO调用,以使应用程序更具响应性 尽管您不能等待构造函数发出的异步调用,但没有什么可以阻止您在不等待调用完成的情况下触发此类调用:
private Configuration()
{
Init();
}
private async void Init()
{
var contents = await FileIO.ReadTextAsync(file);
}
然后可以从Init()
内部设置Configuration
属性。如果实现了INotifyPropertyChanged,则可以在加载值之前将其绑定到UI,加载后UI将刷新
如果您需要检查或等待操作在应用程序中的某个时间点完成,您可以更改Init()
的签名以返回Task
:
private Configuration()
{
InitTask = Init();
}
private async Task Init()
{
var contents = await FileIO.ReadTextAsync(file);
}
public Task InitTask { get; private set; }
现在您可以检查是否已完成:
if (Configuration.Current.IsCompleted)
{
//
}
await Configuration.Current.InitTask;
甚至等待它(如果任务
已经完成,这将立即完成):
编辑:
如果在加载所述文件之前向用户显示任何内容是没有意义的,您可以修改您的输入页面,以选择“视图”:
- 实际视图(您希望用户看到应用程序何时准备就绪)
- 启动屏幕视图(例如显示进度指示器)
您可以基于IsCompleted
属性使正确的一个可见,该属性应在实现了INotifyPropertyChanged
的viewmodel上公开
然后,您可以按如下方式设计页面:
<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>
谢谢,很抱歉出现此错误,我已使用ApplicationData.Current.LocalSettings存储我的设置。在我上面写的示例中,我想说,这是我这个应用程序的默认配置(静态数据/字符串,它们是常量,只有在我更新这个应用程序时才会更改)。::我将示例类的名称更改为“配置”,以使其更清晰。@FrecherxDachs-如果您已经在使用它,请更新您的问题。ApplicationData.Current.LocalSettings的使用不是我的重点,它只是关于如何从文件加载数据并填充Startups上静态类的属性谢谢您的回答,我已经尝试使用INotifyPropertyChanged,但我认为在这里没有帮助。在加载此文件之前,显示我的应用程序的任何页面都没有任何意义。也许可以在启动屏幕显示时加载文件,当加载文件时,启动屏幕消失?有什么建议吗?FrecherxDachs我在我的回答中添加了另一个建议。谢谢你的建议,我会按照你描述的方式来做。该文件非常小,因此不需要进度条,但如果不进行调整,有时会由于种族条件而导致错误行为。非常感谢,祝你今天愉快。:)