debugging UWP在释放模式下丢失序列化数据

5us2dqdw  于 2023-11-22  发布在  其他
关注(0)|答案(1)|浏览(172)

我正在尝试在UWP中制作一个日记应用程序,所以所有的日记条目都保存在一个ObservableCollection中(类型为DiaryEntry,它有三个字符串)。在App类的OnSuspending方法中,我序列化(使用XmlSerializer)并将ObservableCollection保存到应用程序的LocalFolder中。在App类的OnLaunched方法中,我反序列化数据并将其放置在又是可观察的集合。
当我在调试模式下运行这个应用时,它每次都能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(等待GetSavedCollection());
保存集合(到Xml(日志));

4uqofj5v

4uqofj5v1#

我怀疑这是对应用程序生命周期的误解,以及您将代码添加到OnLaunchedOnSuspending方法的地方。
要了解生命周期,请参阅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编译下更明显,我不会感到惊讶。
或者这可能是两个问题的结合。

相关问题