2017-03-14 2 views
0

asyncキーワードなしでラムダ式を使用するLINQ式では、インデックスを指定できます。 exampleの場合:async LINQクエリにインデックスを追加する方法

var list = FileList.Select((file, index) => new { Index=index, Filename=file }); 

asyncキーワードを使用してインデックスを取得しようとしています。例えば:私はインデックスを取得したいと思います

await Task.WhenAll(urlList.Select(async url => 
{ 
    byte[] urlContents = await GetWebPageAsync(url); 
    lock (Locker) { webResults.Add(URLContents); } 
})); 

理由は、Webページの内容ではなく、ロックステートメントを使用してまたはインデックスのために、コレクション内での検索の配列に格納できるようにということです。

上記のクエリにインデックスを追加しようとすると、コンパイラエラーが発生します。

上記のクエリでインデックスを指定する方法はありますか、インデックスを持つ非同期ラムダ式の使用をサポートする別のLINQ式(Select以外)を使用できますか?

+0

あなたの予想に副作用を起こすべきではありません。通常のコードでは十分に悪いですが、マルチスレッドコードを処理する場合は、扱うのがさらに難しくなります。投影を実行するラムダは、操作の結果を返し、リストに追加しません。その後、返されたシーケンスの結果を使用することができます。 – Servy

答えて

0

私が気づいたのは、コードが待ち状態から戻ってきたときにコードが常に単一スレッドになり、常に呼び出されたスレッドと同じスレッド上にあることです。この場合、それはユーザインタフェーススレッドです。したがって、ロックステートメントは必要ありません。彼らはすべて同じ値である

string ThreadID = Thread.CurrentThread.ManagedThreadId.ToString(); 
await Task.WhenAll(urlList.Select(async url => 
{ 
    string TaskThreadID = Thread.CurrentThread.ManagedThreadId.ToString(); 
    byte[] URLContents = await GetWebPageAsync(url); 
    string TaskThreadID2 = Thread.CurrentThread.ManagedThreadId.ToString(); 
    lock (locker) { webResults.Add(URLContents); } 
    })); 

はこれを確認するために、私は、スレッドIDを取得するには、いくつかの呼び出しに入れて。私は、Task.WhenAllメソッドがどのように働いたかについて誤解を持ちました。

この場合でもインデックスは必要ありませんが、参考になることもあります。どのようにして索引が正常に取得されるかを誰かが示すことができれば、私はその答えを受け入れます。

+0

優秀な解決策は、FileList.Select((file、index)=> new {Index = index、Filename = file})の2つのselectステートメントを使用するだけです。 ...}); ' –

+0

@ScottChamberlain私はそれを試してみます。 –

+0

@ScottChamberlainそれはうまくいくように見えますが、コードはコレクション内の各要素に対して新しいオブジェクトを作成します。コレクションが小さい場合は、コレクション内の各URLを順番に検索してインデックスを検索するか、インデックスが大きい場合は辞書を使用するよりも優れているかどうかはわかりません。マイクロソフトでは、通常のLINQと同様に、コレクション内のインデックスを取得するためにasyncで使用できるオーバーロードメソッドを追加する必要があります。 –

関連する問題