4

List (Show は IXmlSerializable を実装するクラス) をローカルの分離ストレージに格納しようとしています。このページのコードを使用しています: http://metrostoragehelper.codeplex.com/ 問題セクションで提案された変更を実装しました。次のコードを使用して、項目リストからクリックされたときに Show オブジェクトを追加しています。

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 リストに表示されます。2 番目の項目がクリックされ、上記のメソッドが呼び出されると、最後の 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() 行ですが、これが含まれている場合でも、Access is Denied という同じエラー メッセージが表示されます。outStream.Dispose() 行も含めると、すぐ下の catch ステートメントで ObjectDisposedException がキャッチされます。他にすべきことはありますか?

4

2 に答える 2

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()。そして、Async で終わる名前を指定すると、次のようになるべきではありませんvoid

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

Serialize の非同期バージョンがあるとは思わないので、そのままTaskEx.Run()です。

于 2012-08-12T19:56:06.667 に答える
0

This block can be shortened to:

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

as you can directly read/write from the stream in the XmlSerializer class.

You may also find that CreationCollisionOption.ReplaceExisting can cause issues and OpenIfExists will cause the file to be overwritten by the serializer as required.

于 2012-08-29T03:54:18.493 に答える