Операция не разрешена в IsolatedStorageFileStream

#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)

смотрите подробности здесь