2013-06-03 65 views
4

當有在不同的線程多次調用Windows.Storage.StorageFolder.GetFolderFromPathAsync我得到ArgumentExceptions時。下面是再現問題的測試:的ArgumentException調用StorageFolder.GetFolderFromPathAsync同時

[TestMethod] 
public async Task ConcurrentGetFolderFromPath() 
{ 
    List<Task> tasks = new List<Task>(); 
    for (int i = 0; i < 10; i++) 
    { 
     var task = Task.Run(async() => 
      { 
       string localFolderPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path; 
       //await Task.Yield(); 
       var folder = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(localFolderPath); 
      }); 

     tasks.Add(task); 
    } 

    await Task.WhenAll(tasks); 
} 

這裏的例外,我得到:

System.ArgumentException: Value does not fall within the expected range. 
Result StackTrace: 
    at Windows.Storage.StorageFolder.GetFolderFromPathAsync(String path) 
    at PCLStorage.Test.FolderTests.<<ConcurrentGetFolderFromPath>b__53>d__55.MoveNext() in c:\git\pclstorage\test\PCLStorage.Test\FolderTests.cs:line 205 

測試始終失敗對我來說,當我通過自身運行它,但一般經過,當我一起運行與其餘的PCL Storage測試。

我在這裏做錯了什麼? GetFolderFromPathAsync或我使用的任何其他API只能從UI線程使用嗎?或者這可能是WinRT存儲API中的一個錯誤?

回答

0

好的,所以這裏的問題是Task.Run之一和它處理async delegates的方式之一。基本上,當你說:

Task.Run(async() => ...) 

什麼它返回給你的是不是純簡Task你期望它。它返回包裹在另一項任務,即任務這個任務。因此,爲了獲得任務了,您正在尋找(即檢索StorageFolder的),你需要await外任務。你可以簡單地,當你將它添加到列表tasks改變這樣做:

tasks.Add(await task); 

現在,有一個第二個問題。你可能在同一時間從同一個文件夾讀取大量的文件。這可能會導致一些AccessExceptions。它也可能不會。這樣做時我會小心點。

我不得不做的文件讀/寫在WinRT的單元測試的問題。幸運的是,我使用MVVM(通過MVVM光),幷包裹着我的本地存儲Controller的內部訪問。這允許我做的是寫一個LocalStorageController只用於單元測試,它允許我將所有的IO都寫入內存中的文件系統(基本上是一個簡單的Dictionary<string, byte[]>)。這確實會使測試複雜文件樹變得更加困難,但您也可以使用不同的數據結構(例如實際Tree)來爲文件系統建模。

無論如何,我希望這會有所幫助。不過,我很抱歉,在你問了這麼久以後。快樂的編碼!

相關問題