2012-10-02 10 views
1

我試圖寫一個文件,但「偶爾」我碰上,我認爲是到併發問題,如的一些時間,我越來越有消息System.UnauthorizedAccessException如何處理StorageFile操作的併發性?

訪問被拒絕。 (異常來自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所以有什麼其他的選擇?

+0

如果這是一個併發問題,你需要鎖定你可能使用SemaphoreSlim.WaitAsync()http://msdn.microsoft.com/en-us/library/hh462788.aspx – Gavin

+0

@mydogisbox這段代碼是用於*保存* –

回答

6

通常,您只是在上一個操作完成之前纔開始下一個操作。

提示:避免async void;改爲使用async Task。這使您能夠知道以前的操作何時完成。

+0

我一直在盯着這個很長一段時間,完全錯過了 - 一直是一個愚蠢的日子,歡呼:) –

+0

僅供參考,*有一個'AsyncLock' [由Stephen Toub開發](http:// blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx),並可在[AsyncEx](http://nitoasyncex.codeplex.com/)中找到。我只是覺得在這種情況下需要它。 –

1

在這裏可能會發生很多事情。正如Stephen上面提到的,你的封裝方法不會返回任務。這意味着無論調用什麼方法SubmitChanges都會以「fire and forget」模式調用它,並且此調用後面的代碼可以並行運行。這大概是不是你想要什麼。

另外,我注意到您正在使用StorageFile.OpenTransacted。我以前沒有使用過,但注意表明OpenTransacted僅在支持ReplaceFile的操作系統上受支持。這個功能實際上允許新文件承擔舊文件的身份,但是我確信如果舊文件打開,操作將失敗。

我不認爲嘗試交換文件的身份會發生,直到成交的文件被關閉,這將發生在處置,它會自動使用聲明由於發生,這是你行有時看到異常。

我會建議您返回一個任務,而我也會考慮使用常規的StorageFile.OpenAsync

+0

我正在使用'OpenTransacted'來避免讀取文件的一半烘焙副本 - 我可能需要考慮我的對象生命週期,因爲它可能是一個觸摸IO密集的時刻... –