#exception #windows-phone-7 #isolatedstorage
#исключение #windows-phone-7 #isolatedstorage
Вопрос:
Я создаю это приложение WP7, которое использует API видеоигр для получения статистики чьего-либо персонажа (просто чтобы помочь изучить silverlight). Он получает данные игроков из веб-службы и сохраняет их в изолированном хранилище на телефоне, чтобы уменьшить нагрузку на сервер.
Изначально у меня был класс, который имел как функцию записи в кэш, так и функцию чтения, но теперь мне пришлось разделить его на два отдельных класса. Класс записи кэша на данный момент не имеет значения, только класс чтения кэша.
В строке 7 выдается исключение со словами «Операция, не разрешенная в IsolatedStorageFileStream.», но только во второй раз, когда создается экземпляр класса. Я выполнил некоторую проверку с помощью debug, и он говорит, что файл определенно существует, но он останавливается после второго предложения using.
Кто-нибудь может мне помочь с этим, пожалуйста? Я чувствую, что упускаю что-то действительно очевидное.
public class CacheReader
{
public PlayerData GetPlayerData(string gamertagIn)
{
using (IsolatedStorageFile CachedReachData = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = CachedReachData.OpenFile(gamertagIn ".xml", FileMode.Open))
{
Debug.WriteLine("Data Retrieved from cache");
XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
PlayerData loadedPlayer = (PlayerData)serializer.Deserialize(stream);
return loadedPlayer;
}
}
}
}
[РЕДАКТИРОВАТЬ 1]
Это трассировка стека, которую я получаю:
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, IsolatedStorageFile isf)
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, IsolatedStorageFile isf)
at System.IO.IsolatedStorage.IsolatedStorageFile.OpenFile(String path, FileMode mode, FileAccess access)
at ReachPhoneApp.CacheReader.GetPlayerFromCache(String gamertagIn)
at ReachPhoneApp.Page2.GetPlayerData()
at ReachPhoneApp.Page2.cacheWriter_UpdateComplete()
at ReachPhoneApp.CacheWriter.WritePlayerDataToCache(String fileNameIn, Object objectIn)
at ReachPhoneApp.CacheWriter.client_GetGameHistoryCompleted(Object sender, GetGameHistoryCompletedEventArgs e)
at ReachPhoneApp.ReachAPI.ReachApiSoapClient.OnGetGameHistoryCompleted(Object state)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMarkamp; stackMark)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMarkamp; stackMark)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at System.Delegate.DynamicInvokeOne(Object[] args)
at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
at System.Delegate.DynamicInvoke(Object[] args)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParamamp; pResult)
Комментарии:
1. Каково значение параметра gamerTagIn при сбое?
2. Извините, я был неправ, этот класс вызывается только один раз, и это единственный раз, когда происходит сбой. Я на 99% уверен, что это проблема только с классом.
3. Я еще ничего не добавил для этого JP, но я использовал debug, чтобы уточнить, что файл существует и имя пользователя совпадает с тем, которое вводится. Спасибо за ответ.
4. Хорошо, я ошибся во второй раз и был прав в первый; класс вызывался один раз раньше, и он работает, но при втором вызове он завершается неудачей. Я предполагаю, что это как-то связано с тем, что файл не был закрыт должным образом? Я предположил, что предложение ‘using’ будет обрабатывать все это.
Ответ №1:
Убедитесь, что у вас каким-то образом нет двух потоков, обращающихся к IsolatedStorage одновременно (т. Е. в VS Debug.View.Потоки и убедитесь, что во время исключения у вас нет нескольких путей через один и тот же код IsoStore).
Это происходило в моем коде WP7 раз в несколько дней, и было сложно найти, поскольку, казалось, это происходило только тогда, когда не подключалось к отладчику.
Комментарии:
1. Я не смог подтвердить это, так как API, который я разрабатывал, с тех пор был закрыт, и я не могу завершить проект. Поскольку он набрал наибольшее количество голосов, я отмечу его как ответ.
2. Есть ли что-нибудь, что вы можете сделать, чтобы даже при одновременном доступе к двум потокам
IsolatedStorage
исключение не выдавалось?
Ответ №2:
Вам нужно вызвать:
stream.Close();
перед
return loadedPlayer;
Комментарии:
1. Это не исправило проблему. Я попытался включить это во все другие методы, которые также обращаются к кэшу. Я собираюсь спросить об этом своего учителя на этой неделе и посмотреть, есть ли у него ответ.
Ответ №3:
Я думаю, проблема в том, что вы не указали, что несколько потоков могут читать / записывать одновременно, указав System.IO.FileShare.Запись на чтение или любой другой доступ, который вам нужен в качестве последнего параметра OpenFile.
Смотрите обсуждение здесь на форумах Microsoft.
Комментарии:
1. Спасибо, я посмотрю на это в ближайшие пару дней. Я не касался этого проекта после того, как застрял на этой ошибке, потому что ни у кого не было ответа.
2. МИЛЛИОН ЗАГРУЗОК. Я думаю, вы только что исправили проблему параллелизма в SterlingDB. 🙂
Ответ №4:
Я также столкнулся с этой проблемой, но по совершенно другим причинам, упомянутым выше. Я не создал каталог, в который сохранял.
private void SaveStringDataToStorage(string sDirectory, string sFileName, string sFileContent)
{
string sPath;
//
using (IsolatedStorageFile oFile = solatedStorageFile.GetUserStoreForApplication())
{
if (!oFile.DirectoryExists(sDirectory))
oFile.CreateDirectory(sDirectory);
//
sPath = Path.Combine(sDirectory, sFileName);
//
using (var oWriter = new StreamWriter(new IsolatedStorageFileStream(sPath, FileMode.Create, oFile)))
oWriter.Write(sFileContent);
}
}
Использование этого кода будет работать, если у вас была та же проблема, что и у меня, плюс это довольно просто, поэтому вы можете адаптировать его ко всему, что вам нужно. Я использовал этот код до того, как у меня возникли проблемы, но я забыл !
, поэтому каталог так и не был создан, ха-ха. Просто типично. Надеюсь, это поможет 🙂
Редактировать
При ближайшем рассмотрении исходного вопроса может оказаться, что файл не существовал. Я думаю, что всегда лучше делать IsolatedStorageFile.DirectoryExists()
и IsolatedStorageFile.FileExists()
, прежде чем пытаться получить доступ к любому местоположению, независимо от того, читаете вы или пишете.
Ответ №5:
По умолчанию при использовании IsolatedStorageFile.OpenFile("filename", FileMode.Open)
ваш файл блокируется этим потоком, и никакой другой поток не сможет получить доступ к этому файлу, пока 1-й поток не закроет его. Но если вы хотите поделиться своим файлом в нескольких потоках только для чтения, я бы рекомендовал вам использовать следующее переопределение
IsolatedStorageFile.OpenFile("filename", FileMode.Open, FileAccess.Read, FileShare.Read)
смотрите подробности здесь