【问题标题】:UWP losing serialize data with release modeUWP 在发布模式下丢失序列化数据
【发布时间】:2017-03-12 16:29:03
【问题描述】:

我正在尝试使用 Visual Studio Community 2015 在 UWP 中制作一个日记应用程序。因此,所有日记条目都保存在 ObservableCollection 中(类型为 DiaryEntry,具有三个字符串)。在 App 类的 OnSuspending 方法中,我序列化(使用 XmlSerializer)并将 ObservableCollection 保存到应用程序的 LocalFolder。在 App 类的 OnLaunched 方法中,我将数据反序列化并再次放入 ObservableCollection。

当我在调试模式下运行此应用程序时,它每次都 100% 运行,但在发布模式下,一旦我关闭并再次打开应用程序,我就会丢失 ObservableCollection。其他时候它可以工作一两次,但我仍然会丢失数据。我想知道的是如何让我的应用在发布模式下运行?

这些是我正在使用的方法:

        private async void SaveCollection(string xml)
    {
        //Serializing our observablecollection and saving it to the local folder
        StorageFile sf = await ApplicationData.Current.LocalFolder.CreateFileAsync("Diary.txt", CreationCollisionOption.ReplaceExisting);
        await Windows.Storage.FileIO.WriteTextAsync(sf, xml);

    }

    private async Task<string> GetSavedCollection()
    {
        try
        {
            Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
            Windows.Storage.StorageFile sampleFile = await storageFolder.GetFileAsync("Diary.txt");

            string text = await Windows.Storage.FileIO.ReadTextAsync(sampleFile);

            return text;
        }
        catch (FileNotFoundException e)
        {
            return "";
        }

    }

    public static string ToXml(ObservableCollection<DiaryEntry> d)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<DiaryEntry>));
        StringBuilder stringBuilder = new StringBuilder();
        XmlWriterSettings settings = new XmlWriterSettings()
        {
            Indent = true,
            OmitXmlDeclaration = true,
        };

        using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, settings))
        {
            serializer.Serialize(xmlWriter, d);
        }
        return stringBuilder.ToString();
    }

    // Deserialize from xml 
    public static ObservableCollection<DiaryEntry> FromXml(string xml)
    {
        if (xml == "")
        {
            return new ObservableCollection<DiaryEntry>();
        }

        XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<DiaryEntry>));
        ObservableCollection<DiaryEntry> value;
        using (StringReader stringReader = new StringReader(xml))
        {
            object deserialized = serializer.Deserialize(stringReader);
            value = (ObservableCollection<DiaryEntry>)deserialized;
        }

        return value;
    }

我是这样称呼这些方法的:

日记 = FromXml(await GetSavedCollection());

SaveCollection(ToXml(Diaries));

【问题讨论】:

  • 在保存数据过程中尝试写一些日志。
  • 你使用哪个NETCore.UniversalWindowsPlatform?努力达到最高。 (5.3.1)。可能这个问题与 .NET Native 工具链有关。
  • 如果在您的应用的构建配置中启用了.NET Native tool chain 选项,则使用Microsoft.NETNative.Analyzer。因此,您可以看到与编译器不兼容的代码。 NuGet 包在这里 => nuget.org/packages/Microsoft.NETNative.Analyzer

标签: debugging uwp release


【解决方案1】:

如果没有完整的代码复制,很难确定(请参阅https://stackoverflow.com/help/mcve),但我怀疑这与对应用程序生命周期的误解以及您将代码添加到 OnLaunched 和 @987654325 的位置有关@ 方法。

要了解生命周期,请参阅the docs herethis blog article

现在这些方法。

让我们先处理OnSuspending,因为这样更简单。您的代码应如下所示:

private void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();

    SaveCollection(ToXml(Diaries));

    deferral.Complete();
}

请注意,如果您在deferral.Complete(); 之后调用SaveCollection,它可能无法在应用程序终止之前完成,并且可能是没有调用的原因

OnLaunching 方法更复杂。我怀疑你有这样的代码:

if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
    //TODO: Load state from previously suspended application
    Diaries = FromXml(await GetSavedCollection());
}

根据模板中的 TODO 注释,这似乎是合乎逻辑的事情,但不适合您希望在重新启动应用程序时始终从磁盘加载的场景。例如,当用户先前关闭应用程序时,上述内容不会加载内容。我假设您也想加载日记条目。 (因为您没有提供完整的重现步骤,我无法确切知道您是如何测试和重现您所看到的行为。)

如果需要,请在 'PrelaunchActivated 检查之前加载日记。

if (Diaries == null)
{
    Diaries = FromXml(await GetSavedCollection());
}

if (e.PrelaunchActivated == false)

这是您如何定义和调用SaveCollection 的问题。

您已将SaveCollection 定义为async void。这是不好的。唯一应该是async void 的是事件处理程序。您应该将其定义为 async Task 并等待调用它:

private async Task SaveCollection(string xml)
{
    System.Diagnostics.Debug.WriteLine(xml);

    //Serializing our observablecollection and saving it to the local folder
    StorageFile sf = await ApplicationData.Current.LocalFolder.CreateFileAsync("Diary.txt", CreationCollisionOption.ReplaceExisting);
    await Windows.Storage.FileIO.WriteTextAsync(sf, xml);
}


await SaveCollection(ToXml(Diaries));

如果不等待此调用,它可能无法正确完成。这种行为在 .NetNative 编译下更加明显,这并不让我感到惊讶。

或者它可能是两个问题的组合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多