代码之家  ›  专栏  ›  技术社区  ›  Rowland Shaw

如何处理StorageFile操作的并发性?

  •  1
  • Rowland Shaw  · 技术社区  · 12 年前

    我试图写入一个文件,但“偶尔”我会遇到一些问题,我认为这些问题是由于并发性造成的 一些 有时,我会得到 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 那么,还有什么其他选择呢?

    2 回复  |  直到 12 年前
        1
  •  6
  •   Stephen Cleary    12 年前

    通常,只有在上一个操作完成后,才能开始下一个操作。

    提示:避免 async void ;使用 async Task 相反这使您能够知道上一个操作何时完成。

        2
  •  1
  •   Jared Bienz - MSFT    12 年前

    这里可能会发生很多事情。正如Stephen上面提到的,封装方法不会返回任务。这意味着无论调用什么方法 提交更改 使用“fire-and-forget”模式调用它,并且此调用之后的代码可以并行运行。这可能是 你想要什么。

    此外,我注意到您正在使用 存储文件打开事务处理 。我以前没有使用过这个,但注意事项表明OpenTransacted仅在支持的操作系统上受支持 ReplaceFile 。这个功能确实允许新文件采用旧文件的身份,但我敢肯定,如果旧文件打开,操作会失败。

    我认为在事务处理文件关闭之前不会尝试交换文件标识,这将在 处置 ,由于 使用 语句,这是您有时看到的异常行。

    我建议您返回一个Task,我也会考虑使用正则表达式 存储文件打开异步