1

我正在尝试写入文件,但“偶尔”我遇到了我认为归结为并发的问题,因为有时,我收到一条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

这里可能会发生很多事情。正如斯蒂芬上面提到的,您的封装方法不会返回任务。这意味着调用SubmitChanges的任何方法都使用“即发即弃”模式调用它,并且该调用之后的代码可以并行运行。这可能不是你想要的。

此外,我注意到您正在使用StorageFile.OpenTransacted我以前没有使用过它,但注释表明 OpenTransacted 仅在支持ReplaceFile的操作系统上受支持。此功能实际上允许新文件假定旧文件的身份,但我很确定如果旧文件打开,该操作将失败。

我认为在事务文件关闭之前不会尝试交换文件身份,这将发生在Dispose上,由于using语句而自动发生,这是您有时会看到异常的行。

我建议您改为返回 Task ,并且我还会考虑使用常规StorageFile.OpenAsync

于 2012-10-02T20:08:44.380 回答