确保数据反序列化/序列化
本文关键字:序列化 反序列化 数据 确保 | 更新日期: 2023-09-27 18:05:33
我有3个ObservableCollections
在我的ViewModel
和一个Class
,我加载当你运行一个应用程序。为了确保ObservableCollections
被反序列化,我刚刚得到。
if(SomeCollection.Count == 0)
ThisCollection = await deserializationMethod<ObservableColletion<T>>(filename);
如果没有文件,deserializationMethod
将用
return Activator.CreateInstance<T>();
这很好,没有问题。
对于class,我有
if(ClassObject.Loaded != true)
ThisObject = await deserializationMethod<T>(filename);
我添加了一个属性-如果文件是反序列化的,那么它是真的。它看起来像它工作,但它不是。这种情况很少发生,但有时文件没有反序列化,当你使用一个应用程序时,这个文件被覆盖,所以每个数据都被销毁。我找不到引起这个问题的原因。你只是运行一个应用程序,它发生了-就像每100次运行一次。
如何非常确定,如果文件存在,那么它肯定会被反序列化?或者我应该把这些ObservableCollections
+ Class
做成List
,然后序列化成一个文件?有什么好的做法吗?
我使用SemaphoreSlim
来确保一切都按照预期使用,但是今天又发生了。
问题是它发生在应用程序启动时,甚至没有其他东西被点击。此刻不可能有什么东西在写。看起来数据没有反序列化或者没有读取存在的文件。因为每个更改都是在关闭应用程序时写的,然后一切都消失了。还有其他想法吗?或者如何确保数据被反序列化?
编辑最终-复制问题:
我终于重现了正在发生的事情。因此,我删除了这里不需要的代码编辑。
我有BackPressed
事件处理当用户要回去或想要退出一个应用程序(如果在MainPage
)。这部分代码显然是导致问题的原因。到底发生了什么。首先,问题是不可能被复制使用模拟器。我的BackPressed
方法包含await和序列化方法,该方法保存了后来消失的数据(因此Ondrej Svejdar已经写入了它,在读取之前正在写入)。但是我开始测试它,有奇怪的行为,我仍然有一些问题。
这是怎么发生的
当我启动一个应用程序(例如偶然)和加载屏幕发生时,我开始点击后退按钮几次->应用程序不运行,它正在关闭ASAP,我甚至看不到UI(有时我能看到AppBar一会儿)。然后,当我尝试再次打开应用程序(不管是否立即或稍后),它是"恢复",在这一刻之后,我的数据消失了。但不是所有的数据。只有在BackPressed
方法中使用await保存的最后一个。只有这一个。我试图保存一个,两个和三个ObservableCollections
有和没有这个类,总是最后一个被保存为"空"。在此等待之后,我得到了Application.Current.Exit()方法,可能会导致这种情况,但我不确定当序列化方法是Task并且只有最后一个被错误序列化时,这是否应该重要。
当我从BackPressed方法中删除这个等待时,我无法重现这个问题,所以就是这样。
我仍然有问题:这种行为是预期的吗?是否有更好的方法来关闭一个应用程序,并确保序列化数据,或者我只是应该保存它在使用一个应用程序,而不是退出它?
如果有人对如何正确地做这件事感兴趣,我正在思考它,并得出一些结论。请记住,这是我的建议,可能有更好的方法。
在处理BackPressedButton事件(硬件)时,我有一个GoBack到上一页的实现(如果不在MainPage上)或如果在MainPage上离开应用程序。我正在使用Application.Current.Exit()关闭一个应用程序,这并没有引起问题(因为我保存了非常小的文件),直到我开始做奇怪的事情(阅读"EDIT FINAL -复制问题:"的问题了解更多细节)。问题是文件没有保存,因为一个应用程序在写完之前就关闭了。解决方法其实很简单。对于我的Save方法,这是一个任务,它应该在写入完成时返回true值,该值应该在关闭应用程序时检查。
bool saved = await saveDataAsync<T>(whichData, dataFileName)
if(saved)
Application.Current.Exit();
和序列化方法看起来像这样(我使用semaphoreSlim,以防有可能有两个方法试图到达同一个文件)
public async Task<bool> saveDataAsync<T>(T whichData, string dataFileName)
{
var Serializer = new DataContractSerializer(typeof(T));
await mySemaphoreSlim.WaitAsync();
try
{
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(dataFileName, CreationCollisionOption.ReplaceExisting))
{
Serializer.WriteObject(stream, whichData);
}
}
finally
{
mySemaphoreSlim.Release();
}
return true;
}