2017-11-02 3 views
0

한 소스에서 데이터를 가져 와서 처리 한 다음 다른 소스에 저장하는 코드 조각을 만들고 있습니다. 양쪽 끝의 대기 시간이 높기 때문에로드 및 저장 작업이 완료 될 때까지 기다리는 동안 async/await를 사용하려고합니다. 이상적으로 이것은 모든 입력 작업을 시작하고 각각이 완료되면 빠른 처리를 수행 한 다음 출력 작업을 시작합니다 - Task.WaitAll을 사용하면 새 작업이 대신 시작될 수있을 때 프로그램이 아무 것도하지 않게됩니다.다른 작업 목록을 차단하지 않고 작업 목록을 기다리는 중

두 번째 비동기 작업은 첫 번째 결과에 따라 달라 지므로 두 번째 비동기 작업을 처리하는 방법을 알아낼 수 없으므로 첫 번째 대기에서 다른 결과 처리를 재개 할 수 있습니다. 결과가 처리되면 두 번째 기다리는 경우, 다른 기능을 처리하기 위해 다시 시작하는 대신 저장 기능이 완료 될 때까지 완전히 차단됩니다. 나는 이와 같은 것을 시도하고 있는데, 내가 뭘 잘못하고 있니?

async Task MainAsync() 
{ 
    /* gets a list of id's */ 

    var dataRequests = ids.Select(id => LoadEntryById(id)).ToList(); 

    foreach(var request in dataRequests) 
    { 
     RawEntry response = await request; 

     ProcessedEntry result = doSomething(response); 

     await SaveResult(result); 
    } 
} 

async Task<RawEntry> LoadEntryById(int id) 
{ 
    /* IO task */ 
} 

async Task SaveResult(ProcessedEntry result) 
{ 
    /* IO task */ 
} 
+0

SaveResult를 기다릴 필요가 없습니다. 대신 목록에 넣고 결국 모두 기다리고 있습니다. – Evk

+2

요청이 이미 정의되어 있고 데이터가 있으므로 "요청 대기 중"의 이유가 없습니다. Line 5는 그 순간 모든 데이터를 가져 와서 List에로드합니다. 그런 다음 foreach는 목록에서 각 항목을 가져옵니다. –

+0

@ 존 Rasch - 나는 어떤 의미로 비동기 물건에 대한 전문가가 아니지만 현재 LoadEntryById ... ToList()가 완료 될 때까지 foreach에 도달하지 않습니다. 이 지점의 코드는 동기식입니다. 첫 번째 'await'은 5 행에 있어야하며 ToListAsync()를 사용해야합니다. –

답변

3

대신 하나의 방법에 기다리고의, 당신의 List<Task> 당신의 지속을 사용하여 다음 Task.WhenAll를 사용을 만들 :

var tasks = ids.Select(async id => { 
    var response = await LoadEntryById(id); 
    var result = doSomething(response); 
    await SaveResult(result); 
}).ToList(); 

await Task.WhenAll(tasks); 

이 비동기 방식으로 모든 작업을 처리합니다. 이 설정 LoadEntryById에서

Parallel.Foreach(ids.Select(id => LoadEntryById(id)), (rawEntry) => { 
    var result = doSomething(rawEntry); 

    await SaveResult(result); 
} 

RawEntry LoadEntryById(int id) 
{ 
    /* IO task */ 
} 

async Task SaveResult(ProcessedEntry result) 
{ 
    /* IO task */ 
} 

이 작업을 반환 할 필요가 없습니다, 그러나하고있는 무슨이 따라 달라

-1

내가 제대로 이해하면, 당신이 이것을 시도 할 수 있습니다.

관련 문제