4

異なるスレッドで 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 または私が使用している他の A​​PI は、UI スレッドからのみ使用することになっていますか? それとも、これは WinRT ストレージ API のバグでしょうか?

4

1 に答える 1

0

さて、ここでの問題は の 1 つでTask.Runあり、その処理方法async delegatesです。基本的に、あなたが言うとき:

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

Taskそれがあなたに返しているのは、あなたが期待している普通のジェーンではありません。別の task 、つまり Task にラップされたそのタスクを返しています。したがって、探しているタスク (StorageFolder を取得するタスク) を取得するにawaitは、外側のタスクが必要です。tasksリストに追加するときに変更するだけで、これを行うことができます。

tasks.Add(await task);

さて、2 つ目の問題があります。おそらくすべて同時に同じフォルダーから大量の読み取りを行っています。これは、いくつかの原因となる場合がありますAccessExceptions。そうでない場合もあります。これを行うときは注意が必要です。

WinRT の単体テストでファイルの読み取り/書き込みに問題がありました。幸いなことに、私は (Mvvm Light を通じて) Mvvm を使用しており、Controller. これLocalStorageControllerにより、メモリ内のファイルシステムに対してすべての IO を実行できる単体テスト用の を作成することができます (基本的には単純なDictionary<string, byte[]>)。これにより、複雑なファイル ツリーのテストが少し難しくなりますが、別のデータ構造 (実際の などTree) を使用してファイル システムをモデル化することもできます。

とにかく、これが役立つことを願っています。質問してから時間が経ってしまい申し訳ありません。ハッピーコーディング!

于 2013-07-18T22:01:41.537 に答える