Как определить степень параллелизма в теле цикла, состоящем из операций с процессором и операциями ввода-вывода? - PullRequest
0 голосов
/ 13 декабря 2018

Я использую цикл ForEachAsync, как описано в этом сообщении в блоге на ссылка .

В моем теле цикла выполняется комбинация операций ввода-вывода (асинхронное / ожидание) и операций с привязкой к процессору.В таком случае, какие все факторы необходимо учитывать для определения степени параллелизма?

public static Task ForEachAsync<T>(
    this IEnumerable<T> source,
    int degreeOfParallelism,
    Func<T, Task> body)
{
    if (degreeOfParallelism <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(degreeOfParallelism));
    }

    return Task.WhenAll(
        from partition in Partitioner
                          .Create(source)
                          .GetPartitions(degreeOfParallelism)
        select Task.Run(async () =>
        {
            using (partition)
            {
                while (partition.MoveNext())
                {
                    await body(partition.Current);
                }
            }
        }));
}

public async Task ProcessChangesAsync(
    IChangeFeedObserverContext context,
    IReadOnlyList<Document> docs,
    CancellationToken cancellationToken)
{
    // This function receives list of documents that need to be processed in parallel
    await docs.ForEachAsync(8, async doc =>
    {
        await ProcessDocument(doc);
    });
}

public async Task ProcessDocument(Document doc)
{
    // We get other details for this entity from database.
    var dbResult = await repository.GetDetailsFromDB(doc);

    // Get some more data from external services
    var moreDetails = await httpClient.GetMoreDataFromOtherServices(dbResult);

    // The data fetched above consists of list of elements and we iterate over the list and run business logic.
    // Use data mappers to convert the data back to entities. These are all CPU bound operations

    // Then finally we persist details in DB
    await repository.WriteToDB(...);
}

1 Ответ

0 голосов
/ 14 декабря 2018

Если вы не хотите ограничить количество запущенных задач, почему бы не позволить системе и самой работе работать по-своему?

public static Task ForEachAsync<T>(this IEnumerable<T> source, Func<T, Task> body)
    => Task.WhenAll(from item in source select body(item));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...