3

我想编写一个 Win8 应用程序,在那里我使用一个Configuration带有static成员的 -class,该成员在启动时加载一次,并且可以在运行时从任何地方访问。

所以,主要问题是,默认设置存储在一个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-class 的设计。任何建议/提示都会很好。

4

2 回答 2

4

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

尽管您不能await从构造函数进行异步调用,但没有什么能阻止您在不等待它们完成的情况下触发此类调用:

private Configuration()
{
    Init();
}

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

然后,您可以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; }

现在可以检查是否完成:

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>
于 2013-04-30T04:35:54.627 回答
1

您不需要其他类来存储设置 -AplicationData.Current.LocalSettings为每个 Windows 8 应用程序提供了字典,每次启动应用程序时都会自动加载该字典,并且您无需await关键字即可阅读 - 例如:

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

object value = settings.Values["MyIndex"];
if (value != null)
{
     int myIndex = (int)value;
     //...
}
于 2013-04-29T09:10:44.937 回答