1

ファイルに書き込もうとしていますが、「ときどき」同時実行性に起因すると思われる問題に遭遇します。ときどきwithメッセージSystem.UnauthorizedAccessExceptionが表示されます。

アクセスが拒否されました。(HRESULT からの例外: 0x80070005 (E_ACCESSDENIED))

…以下より。

public async void SubmitChanges()
{
    DataContractSerializer serializer = 
        new DataContractSerializer(typeof(LocalCache<T>));

    StorageFile file = await ApplicationData.Current.LocalFolder
            .CreateFileAsync(GetFileNameForType(), 
                CreationCollisionOption.ReplaceExisting);

    //Occasionally throws here
    using (var fi = await file.OpenTransactedWriteAsync())
    {
        serializer.WriteObject(fi.Stream.AsStreamForWrite(), this);
        await fi.CommitAsync();
    }
}

これは何らかの同時実行性によるものか、または別の場所で読み取り用にまだ開いているとしか考えられませんが、それが利用可能になるのを待つ方法を見つけることができないようです-私は通常lockそれを回避しますが、これは許可されていないawaitので、他のオプションは何ですか?

4

2 に答える 2

6

通常、前の操作が完了するまで次の操作を開始しないだけです。

ヒント: 避けてくださいasync void。代わりに使用async Taskします。これにより、前の操作がいつ完了したかを知ることができます。

于 2012-10-02T19:55:01.203 に答える
1

ここで起こりうることがいくつかあります。Stephen が上で述べたように、カプセル化メソッドはタスクを返しません。これは、どのメソッドがSubmitChangesを呼び出していても、「ファイア アンド フォーゲット」パターンで呼び出していることを意味し、この呼び出しに続くコードは並行して実行できます。これはおそらくあなたが望むものではありません。

さらに、StorageFile.OpenTransactedを使用していることに気付きました。これは以前に使用したことはありませんが、 OpenTransacted はReplaceFileをサポートするオペレーティング システムでのみサポートされていることを示しています。この機能により、文字通り、新しいファイルが古いファイルのアイデンティティを引き継ぐことができますが、古いファイルが開いていると操作が失敗することは間違いありません。

Disposeで発生するトランザクション ファイルが閉じられるまで、ファイル ID を交換しようとする試みは発生しないと思います。これは、例外が発生することがある行であるusingステートメントのために自動的に発生します。

代わりに Task を返すことをお勧めします。通常のStorageFile.OpenAsyncの使用も検討します。

于 2012-10-02T20:08:44.380 に答える