Windows RT - StorageFile的同步使用

时间:2013-04-29 08:54:04

标签: c# windows-runtime async-await 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
    }
}

我不确定,如何解决这个问题,我可能需要更改Configuration - 类的设计。任何建议/提示都会很好。

2 个答案:

答案 0 :(得分:4)

这是一项设计决定,不允许任何可能需要超过50毫秒的同步调用,即任何文件或网络IO调用,以使应用程序更具响应性。

虽然您无法await来自构造函数的异步调用,但没有任何东西阻止您在不等待它们完成的情况下触发此类调用:

private Configuration()
{
    Init();
}

private async void Init()
{
    var contents = await FileIO.ReadTextAsync(file);
}

然后,您可以在Configuration内设置Init()属性。如果您实现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它(如果Task已经完成,这将立即完成):

await Configuration.Current.InitTask;

编辑:

如果在加载所述文件之前向用户显示任何内容没有意义,您可以修改您的输入页面以使用其他“视图”:

  • 实际视图(您希望用户查看应用何时就绪)
  • 启动画面视图(例如显示进度指示器)

您可以根据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>

答案 1 :(得分:1)

您不需要另一个类来存储设置 - 为每个Windows 8应用程序提供AplicationData.Current.LocalSettings字典,每次启动应用程序时都会自动加载该字典,而您在没有await关键字的情况下阅读它例如:

var settings = ApplicationData.Current.LocalSettings;
settings.Values["MyIndex"] = 2;

object value = settings.Values["MyIndex"];
if (value != null)
{
     int myIndex = (int)value;
     //...
}