2012-08-12 37 views
4

我試圖將一個List(其中Show是我的類實現IXmlSerializable)存儲到本地獨立存儲。我正在使用此頁面的代碼: http://metrostoragehelper.codeplex.com/ 我已經實施了「問題」部分中建議的更改。 我使用以下代碼在從項目列表中單擊時添加一個Show對象。在本地存儲中保存對象時訪問被拒絕Windows 8 Metro App

private async void addShowButton_Click_1(object sender, RoutedEventArgs e) 
    { 
     var isoStorage = new StorageHelper<List<Show>>(StorageType.Local); 

     List<Show> currentShows = await isoStorage.LoadASync("myShowsEx"); 
     if(currentShows == null) { 
      currentShows = new List<Show>(); 
     } 

     currentShows.Add(currentShow); 

     isoStorage.SaveASync(currentShows, "myShowsEx"); 


     //Read it back, for debugging to check if it has been added properly. 
     List<Show> currentShowsRB = await isoStorage.LoadASync("myShowsEx"); //Exception here 

    } 

第一個節目添加得非常好,它顯示在currentShowsRB列表中。當第二個項目被點擊並且上面的方法調用了最後一次LoadAsync調用時發生的異常:訪問被拒絕。 (來自HRESULT的異常:0x80070005(E_ACCESSDENIED)) 如何解決此問題以訪問多個調用的本地數據存儲?

下面也從StorageHelper相關代碼:

public async void SaveASync(T Obj, string FileName) 
    { 

     FileName = FileName + ".xml"; 
     try 
     { 
      if (Obj != null) 
      { 
       StorageFile file = null; 
       StorageFolder folder = GetFolder(storageType); 
       file = await folder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting); 

       using (var writeStream = await file.OpenAsync(FileAccessMode.ReadWrite)) 
       { 
        Stream outStream = Task.Run(() => writeStream.AsStreamForWrite()).Result; 
        serializer.Serialize(outStream, Obj); 
        //writeStream.Dispose(); //Added and we get UnauthorizedAccessException 
        // outStream.Dispose(); //Added ObjectDisposedException caught in catch statement below 
       } 
      } 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
    } 
    public async Task<T> LoadASync(string FileName) 
    { 
     FileName = FileName + ".xml"; 
     try 
     { 
      StorageFile file = null; 
      StorageFolder folder = GetFolder(storageType); 
      file = await folder.GetFileAsync(FileName); 
      using (var readStream = await file.OpenAsync(FileAccessMode.Read)) 
      { 
       Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result; 
       inStream.Position = 0; 
       return (T)serializer.Deserialize(inStream); 
      } 
     } 
     catch (FileNotFoundException) 
     { 
      //file not existing is perfectly valid so simply return the default 
      return default(T); 
      //throw; 
     } 
     catch (Exception) 
     { 
      //Unable to load contents of file 
      throw; 
     } 
    } 

我加入的writeStream.Dispose()線,但即使這是包括我得到訪問相同的錯誤消息被拒絕。如果我還包含outStream.Dispose()行,則會在下面的catch語句中捕獲ObjectDisposedException。還有什麼我應該做的?

回答

2

您不等待SaveAsync完成,試圖在保存仍在進行時加載。將其更改爲:

//isoStorage.SaveASync(currentShows, "myShowsEx"); 
await isoStorage.SaveASync(currentShows, "myShowsEx"); 

List<Show> currentShowsRB = await isoStorage.LoadASync("myShowsEx"); 

編輯,await荷蘭國際集團在void是一個標準問題。
速戰速決是:

await TaskEx.Run(() => isoStorage.SaveASync(currentShows, "myShowsEx")); 

但你也可以移動TaskEx.Run()SaveASync()。而鑑於與異步結尾的名稱,它不應該是void但:

Task SaveASyncT Obj, string FileName) 
{ 
    return TaskEx.Run() => { .... } 
} 

我不相信有序列化的異步版本,所以它停留在TaskEx.Run()

+0

謝謝!你不能等待void方法,所以我必須創建一個虛擬返回類型。有比返回默認(T)更優雅的解決方案嗎? – TheSteak 2012-08-12 21:04:43

+0

請參閱編輯。 .......................... – 2012-08-12 21:46:30

0

該塊可以被簡化爲:

 using (var readStream = await file.OpenAsync(FileAccessMode.Read)) 
     { 
      return (T)serializer.Deserialize(readStream); 
     } 

,你可以直接讀取從XmlSerializer類流/寫。

您可能還會發現CreationCollisionOption.ReplaceExisting會導致問題,並且OpenIfExists會根據需要導致文件被序列化器覆蓋。