оригинал
foreach (file in files)
{
ReadTheFileAndComputeAFewThings(file);
CallAWebService(file);
MakeAFewDbCalls(file);
}
оригинал + асин c (лучше, чем выше, зависит!)
foreach (file in files)
{
await ReadTheFileAndComputeAFewThings(file);
await CallAWebService(file);
await MakeAFewDbCalls(file);
}
Это не будет лучше, если вызовы на самом деле не будут реализуя асин c, тогда будет хуже. Еще один способ, которым это будет хуже, - если асин c -несс так короток, что он перевесит стоимость задачи. Каждый asyn c Task создает управляемый поток, который возвращает 1 МБ из системы и добавляет время синхронизации потока. Несмотря на то, что синхронизация крайне мала, если это сделать в сжатые сроки, l oop будет видеть проблемы с производительностью.
Ключом здесь является то, что Задача должна быть на самом деле асинхронной c версии.
Параллельно (лучше, чем выше, зависит!)
Parallel.ForEach(files, item)
{
ReadTheFileAndComputeAFewThings(item);
CallAWebService(item);
MakeAFewDbCalls(item);
}
Если все это может произойти одновременно, тогда это лучше. Кроме того, только если вы хотите назначить несколько потоков, ресурсы, помните, что ресурсы ограничены, на вашем компьютере только столько ядер и оперативной памяти, вы можете управлять этим в зависимости от того, за что еще отвечает оборудование.
Не лучше, если методы не являются поточно-ориентированными.
Parallel + asyn c (лучше, чем выше, зависит!)
Parallel.ForEach(files, item)
{
await ReadTheFileAndComputeAFewThings(item);
await CallAWebService(item);
await MakeAFewDbCalls(item);
}
FYI - Parallel + asyn c пример выше на самом деле неверен !!! Так как сам Parallel.ForEach не является асинхронным c, вам нужно будет провести некоторое исследование относительно того, как построить асинхронную c версию Parallel.ForEach
Также те же самые комментарии выше применяются при использовании в сочетании.
Обновление
на основе комментария, это в значительной степени зависит от того, был ли установлен ConfigureAwait (), но при условии, что вы этого не сделали. Кроме того, это не будет оправданием, так что если CallAWebService зависит от ReadTheFileAndComputeAFewThings, то, вероятно, что-то пойдет не так.
foreach (file in files)
{
List<Task> jobs = new List<Task>();
jobs.Add(ReadTheFileAndComputeAFewThings(file))
jobs.Add(CallAWebService(file))
jobs.Add(MakeAFewDbCalls(file))
Task.WhenAll(jobs.ToArray());
}
или ...
List<Task> jobs = new List<Task>();
foreach (file in files)
{
jobs .Add(ReadTheFileAndComputeAFewThings(file))
jobs .Add(CallAWebService(file))
jobs .Add(MakeAFewDbCalls(file))
}
Task.WhenAll(jobs.ToArray());
разница между ними состоит в том, что у одного намного больше задач, и вы, вероятно, столкнетесь с проблемами с позже относительно контекста .... он же перечислитель больше не будет иметь правильного «индекса» для файла, и если один вызов зависел от другого, выполняемого первым.
Удивительная ссылка объяснение асин c ... https://docs.microsoft.com/en-us/archive/blogs/benwilli/tasks-are-still-not-threads-and-async-is-not-parallel