Самый быстрый / самый эффективный способ параллельного вызова списка делегатов в .NET Core 5 [closed]

Вот 2 примера:

List<Func<Reference>> referenceDelegates = new List<Func<Reference>>();

foreach (string url in urls)
{
    // not async as I need to add this to a list without invoking it.
    // making it async would require a return type of Task<Reference> and 
    // force the task to execute when adding it to a list
    // e.g. referenceDelegates.Add(GetReference());
    Reference GetReference()
    {
        // uses the url string and gets data from a bunch of different servers
        // from around the world, a different server with each foreach iteration
        // returns Result;
    }
    referenceDelegates.Add(GetReference);
}

List<Task<Reference>> referenceTasks = referenceDelegates
    .AsParallel()
    .Select(d => Task.Run(d.Invoke))
    .ToList();

List<Reference> references = Task.WhenAll(referenceTasks)
    .Result
    .ToList();

// work with results

или же

List<Func<Task<Reference>>> referenceDelegates = new List<Func<Task<Reference>>>();
foreach (string url in urls)
{        
    async Task<Reference> GetReference()
    {
        // uses the url string and gets data from a bunch of different servers
        // from around the world, a different server with each foreach iteration
        // returns Result;
    }
    referenceDelegates.Add(GetReference);
}

List<Task<Reference>> referenceTasks = referenceDelegates
    .AsParallel()
    .Select(d => Task.Run(d.Invoke))
    .ToList();

Task.WhenAll(referenceTasks);

List<Reference> result = referenceTasks
    .Select(l => l.Result)
    .ToList();

// work with results

Что это за самый эффективный (самый быстрый с наименьшим объемом памяти) способ одновременно вызвать список делегатов и дождаться результата?

Может, его можно переписать?

1 ответ
1

Я предлагаю вам просто попробовать и посмотреть, но, что более важно, я сомневаюсь, что это важно.

Поскольку это задачи, которые запрашивают результаты с других серверов в Интернете, время, необходимое для их добавления в список и их вызова, будет неизмеримо мало по сравнению с тем, сколько времени на самом деле требуется для выполнения каждого из них. Только по этой причине они все должны быть Task<Reference> в любом случае, и их вызов не будет блокироваться, поэтому вы можете добавить их все в задачу, а затем подождать.

То, что вы хотите, вероятно, будет примерно таким:

List<Task<Reference>> referenceTasks = new List<Task<Reference>>();
foreach (string url in urls)
{        
    async Task<Reference> GetReference()
    {
        // uses the url string and gets data from a bunch of different servers
        // from around the world, a different server with each foreach iteration
        // returns Result;
    }
    referenceTasks.Add(GetReference());
}

await Task.WhenAll(referenceTasks);

List<Reference> results = new List<Reference>();
foreach(var r in referenceTasks)
{
    results.Add(await r);
}

// work with results

  • 1

    Почему вы определяете одну и ту же локальную функцию (n раз) внутри цикла foreach?

    — Питер Чала


  • Это так, как было написано в вопросе, вы можете предположить, что это какое-то закрытие над url.

    — Турксарама

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *