2017-03-14 10 views
0

async 키워드없이 람다 식을 사용하는 LINQ 식은 인덱스를 지정할 수 있습니다. example의 경우 :async LINQ 쿼리에 인덱스를 추가하는 방법

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

나는 비동기 키워드를 사용하는 동안 인덱스를 얻기 위해 노력하고 있어요. 예를 들면 :

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

내가 웹 페이지의 내용이 잠금 문을 사용하거나 인덱스 컬렉션 내에서 검색하는 대신 배열에 저장 될 수 있도록 인덱스가 취득하고자하는 이유.

위의 쿼리에 인덱스를 추가하려고하면 컴파일러 오류가 발생합니다.

위의 쿼리에서 인덱스를 지정하는 방법이 있습니까? 아니면 인덱스가있는 비동기 람다 식을 사용하도록 지원하는 다른 LINQ 식 (선택 제외)을 사용할 수 있습니까?

+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})라는 두 개의 Select 문을 사용하면됩니다 (async data => {foo = data.Index; ...}); ' –

+0

@ ScottChamberlain 나는 그것을 시도 할 것이다. –

+0

@ScottChamberlain 작동하는 것처럼 보이지만 코드는 컬렉션의 각 요소에 대해 새 개체를 만듭니다. 컬렉션이 작을 때 컬렉션 내의 각 URL에 대해 순차적 검색을 수행하는 것보다 인덱스가 더 길 때 사전을 사용하거나 사전을 사용하는 것이 더 낳은 것인지 잘 모르겠습니다. Microsoft는 일반 LINQ와 마찬가지로 컬렉션 내의 인덱스를 얻기 위해 async와 함께 사용할 수있는 오버로드 메서드를 추가해야합니다. –

관련 문제