In my Silverlight/XNA app/game I save and load a custom class Level.cs to Isolated Storage. I serialize and deserialize the level using SharpSerializer. The code below is combined from several tutorials on saving and serializing. The code works most of the time, but if I save and load a level repeatedly, usually 2 or 3 times, I will get an exception thrown in the Load() method. I have been unable to track down the cause of this exception. Right now I am handling it by restarting the level from the default XML file when this occurs.
My Questions:
1.) Do you know what is causing my exception, and how can I fix it?
2.) Are there any additional details in the Exception that I am catching that might help me track down what is causing this?
3.) Is there a better method for structuring this code? Most examples I have found use "using" statements. Is there an advantage to that method that might help me here?
Additional Details:
The strange part is that if I quit the app without saving and then run the app again, it will successfully load the Isolated Storage file that it just failed to load. This leads me to believe that the save file is not corrupted, but that I am likely not disposing of some resources properly each time I save/load and as those resources build up during an instance of running the app, it eventually causes this issue.
When the exception is thrown, it is always thrown by this line in the Load() method:
LoadStream = LoadStorage.OpenFile(loadName, FileMode.Open);
The exception description is {"Operation not permitted on IsolatedStorageFileStream."}. Are there any other relavant details in the exception that I should look for? The inner exception could not be read.
My method for saving:
public void Save()
{
IsolatedStorageFile SaveStorage = null;
SaveStorage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream SaveStream = null;
string saveLName = "levelSave_" + currentLevel.info.number + ".XML";
if (SaveStorage.FileExists(saveLName))
{
SaveStorage.DeleteFile(saveLName);
}
try
{
SaveStream = SaveStorage.CreateFile(saveLName);
var serializer = new SharpSerializer();
serializer.Serialize(currentLevel, SaveStream);
saveState = SaveState.Successful;
}
catch (Exception ex)
{
saveState = SaveState.Failed;
}
finally
{
if (SaveStream != null)
{
SaveStream.Close();
SaveStream.Dispose();
} if (SaveStorage != null)
{
SaveStorage.Dispose();
}
}
}
My method for loading:
public Level LoadLevel(int levelNumber)
{
IsolatedStorageFile LoadStorage;
LoadStorage = IsolatedStorageFile.GetUserStoreForApplication();
Level tmpLevel;
string loadName = "levelSave_" + levelNumber + ".XML";
if (LoadStorage.FileExists(loadName))
{
IsolatedStorageFileStream LoadStream = null;
try
{
LoadStream = LoadStorage.OpenFile(loadName, FileMode.Open);
var serializer = new SharpSerializer();
tmpLevel = (Level)serializer.Deserialize(LoadStream);
}
catch (Exception ex)
{
tmpLevel = LoadLevelXML(levelNumber);
// Level failed to load from save,
// restart unsaved level from beginning
}
finally
{
if (LoadStream != null)
{
LoadStream.Close();
LoadStream.Dispose();
}
if (LoadStorage != null)
{
LoadStorage.Dispose();
}
}
}
else
{
tmpLevel = LoadLevelXML(levelNumber);
// Level save file not found,
// restart unsaved level from beginning
}
return tmpLevel;
}
I believe this code is probably unnecessary in the Save() method. I just added it to make sure overwriting a file was not the problem.
if (SaveStorage.FileExists(saveLName))
{
SaveStorage.DeleteFile(saveLName);
}
I also believe that this code in both methods is unnecessary, but again, I added it to ensure that the "storage" floating around was not the issue.
if (LoadStorage != null)
{
LoadStorage.Dispose();
}
The exception was thrown before I added either of those segments of code.
Save
andLoad
method executes simultaneously? Try uselock
statement to make it thread-safe – Ku6oprIsolatedFileStorage
only supports a small amount of data by default. You also should use ausing
-statement instead of rolling your own with atry...finally
. – user7116