Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Windows RT-StorageFile的同步使用_C#_Windows Runtime_Async Await_Storagefile - Fatal编程技术网

C# Windows RT-StorageFile的同步使用

C# Windows RT-StorageFile的同步使用,c#,windows-runtime,async-await,storagefile,C#,Windows Runtime,Async Await,Storagefile,我想写一个Win8应用程序,在那里我使用一个配置-类和一个静态成员,它在启动时加载一次,在运行时可以从任何地方访问 因此,主要问题是,默认设置存储在xml文件中,但读取文件内容是异步的(StorageFile),但我没有找到任何解决方案来等待,直到文件完全加载,因为不可能在任何情况下(主线程、构造函数)都使用wait,在我看来,这是一个设计问题。 如果在访问配置数据之前未完全读取文件,则此应用程序将出现错误行为 下面是一个示例代码: public class Configuration {

我想写一个Win8应用程序,在那里我使用一个
配置
-类和一个
静态
成员,它在启动时加载一次,在运行时可以从任何地方访问

因此,主要问题是,默认设置存储在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我在我的回答中添加了另一个建议。谢谢你的建议,我会按照你描述的方式来做。该文件非常小,因此不需要进度条,但如果不进行调整,有时会由于种族条件而导致错误行为。非常感谢,祝你今天愉快。:)