3

저는 Windows 서비스를 작성 중이며 각 루프가 비동기 (TAP) 메소드를 호출하는 여러 foreach 루프를 병렬로 실행하는 방법을 찾고 있습니다. 나는 처음에는 Parallel.ForEach와 async/await가 호환되지 않기 때문에 작동하지 않는 다음 코드를 시도했다. 누구든지 이것을 달성 할 수있는 대체 접근법이 있는지 알고 있습니까? 가 SendAsync()가 직렬로 실행해야 foreach 루프의 각 사본을 조작하는 방식으로 인해 명료성을 위하여, 용 async를 사용하는 루프의 병렬 실행

Parallel.ForEach(messagesByFromNumber, async messageGroup => 
{ 
    foreach (var message in messageGroup) 
    { 
     await message.SendAsync(); 
    } 
}); 

; 즉, foreach 루프는 동시/병렬이 될 수 없습니다.

+0

비동기 호출이 화재 및 잊어 버린 형식 메서드이기 때문에 병렬이 전혀 필요 없다고 완전히 확신 할 수 없습니다. 그냥 각각에 대한 표준을 수행하고 비동기 메서드는 당신이 뭘 원하는 가까이에 뭔가를해야합니다 화재 – theDarse

+0

@theDarse SendAsync() 메서드가 너무 느리기 때문에 외부 루프로 표준 foreach를 사용할 수없는 이유입니다 별도의 스레드에서 실행할 수있는 외부 루프가 필요하다는 것을 알았습니다. 두 개의 중첩 표준 foreach 루프를 수행하는 것은 너무 오래 걸릴 것입니다. –

+0

병렬 및 비동기 코드를 혼합하지 마십시오. 스레드 (일반적으로 I/O 호출)를 구울 때 비동기를 사용하고, 병렬은 모든 코어에서 병렬로 CPU 집약적 인 계산을 실행하기위한 것입니다. – thoean

답변

4

목표를 동시에 실행하려면 Parallel.Foreach을 사용할 필요가 없습니다. 간단히 Task.WhenAll로 한 번에 await에게 모두 SendAsyncforeach이 모든 작업을 얻을 않는 각 그룹에 대한 작업을 생성, 모든 그룹을 통해 이동하고 :

var tasks = messagesByFromNumber.Select(async messageGroup => 
{ 
    foreach (var message in messageGroup) 
    { 
     await message.SendAsync(); 
    } 
}); 
await Task.WhenAll(tasks) 
+1

그런 식으로 async를 select 문에서 사용할 수 있는지 전혀 알지 못했습니다. 그냥 솔루션을 시도하고 원하는대로 코드가 실행됩니다. 정말 고마워! –

+0

@JeffGlazier 확실 ... 언제든지. – i3arnon

0

당신은 AsyncEnumerator NuGet Package으로 더 클리트를 할 수 있습니다 :

using System.Collections.Async; 

await messagesByFromNumber.ParallelForEachAsync(async messageGroup => 
{ 
    foreach (var message in messageGroup) 
    { 
     await message.SendAsync(); 
    } 
}, maxDegreeOfParallelism: 10);