I'm having a method which calls a WCF service multiple times in parallel. To prevent an overload on the target system, I want to use PLinq's ability to limit the number of parallel executions. Now I wonder how I could rewrite my method in an efficient way.
Here's my current implementation:
private async Task RunFullImport(IProgress<float> progress) {
    var dataEntryCache = new ConcurrentHashSet<int>();
    using var client = new ESBClient(); // WCF
    // Progress counters helpers
    float totalSteps = 1f / companyGroup.Count();
    int currentStep = 0;
    //Iterate over all resources
    await Task.WhenAll(companyGroup.Select(async res => {
        getWorkOrderForResourceDataSetResponse worResp = await client.getWorkOrderForResourceDataSetAsync(
            new getWorkOrderForResourceDataSetRequest(
                "?",
                res.Company,
                res.ResourceNumber,
                res.ResourceType,
                res.CLSName,
                fromDate,
                toDate,
                "D"
            )
        );
        // Iterate over all work orders and add them to the list
        foreach (dsyWorkOrder02TtyWorkOrderResource workOrder in worResp.dsyWorkOrder02) {
            dataEntryCache.Add(workOrder.DataEntryNumber.Value);
        }
        // Update progress
        progress.Report(totalSteps * Interlocked.Increment(ref currentStep) * .1f);
    }));
    // Do some more stuff with the result
}
I already tried some approaches to use PLinq instead, but I don't quite come up with a proper solution. This is my current state.
var p = companyGroup.Select(res => client.getWorkOrderForResourceDataSetAsync(
    new getWorkOrderForResourceDataSetRequest(
        "?",
        res.Company,
        res.ResourceNumber,
        res.ResourceType,
        res.CLSName,
        fromDate,
        toDate,
        "D"
    )
).ContinueWith(worResp => {
    // Iterate over all work orders and add them to the list
    foreach (dsyWorkOrder02TtyWorkOrderResource workOrder in worResp.Result.dsyWorkOrder02) {
        dataEntryCache.Add(workOrder.DataEntryNumber.Value);
    }
    // Update progress
    progress.Report(totalSteps * Interlocked.Increment(ref currentStep) * .1f);
}));
await Task.WhenAll(p.AsParallel().ToArray());
This, quite obviously, doesn't work properly. Do you have any suggestions to make it work properly and efficient and to limit the maximum calls to the server so 8 in parallel?
 
    