当在不同的线程上多次调用Windows.Storage.StorageFolder.GetFolderFromPathAsync时,我收到了ArgumentExceptions。这是一个重现问题的测试:
[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 :(得分:0)
好的,所以这里的问题是Task.Run
之一以及它处理async delegates
的方式。基本上,当你说:
Task.Run(async () => ...)
它归还给你的不是你期望它的简单Task
。它将该任务包装在另一个任务中,即一个任务。因此,为了完成您正在寻找的任务(检索StorageFolder的任务),您需要await
外部任务。您只需在将其添加到tasks
列表时进行更改即可完成此操作:
tasks.Add(await task);
现在,还有第二个问题。你可能同时在同一个文件夹中进行一堆阅读。这可能会导致一些AccessExceptions
。它也可能不会。这样做我会小心的。
我在WinRT中进行单元测试中的文件读/写时遇到了问题。幸运的是,我正在使用Mvvm(通过Mvvm Light)并将我的本地存储包装在Controller
内。这让我能做的就是为单元测试编写一个LocalStorageController
,允许我将所有IO都写入内存中的文件系统(基本上是一个简单的Dictionary<string, byte[]>
)。这确实使测试复杂文件树变得更加困难,但您也可以使用不同的数据结构(例如实际Tree
)来建模文件系统。
无论如何,我希望这会有所帮助。我很抱歉,你问这个问题已经很久了。快乐的编码!