同时调用StorageFolder.GetFolderFromPathAsync时出现ArgumentException

时间:2013-06-03 04:09:15

标签: .net windows-runtime windows-store-apps

当在不同的线程上多次调用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中的错误?

1 个答案:

答案 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)来建模文件系统。

无论如何,我希望这会有所帮助。我很抱歉,你问这个问题已经很久了。快乐的编码!