Так что я провел большую часть ночи, пытаясь понять это.
Мне посчастливилось вчера познакомиться с parallel.foreach, и он работает так, как я хочу, за исключением одной детали.
У меня есть следующее:
Parallel.ForEach(data, (d) =>
{
try
{
MyMethod(d, measurements);
}
catch (Exception e)
{
// logg
}
});
В методе «MyMethod» у меня есть много логики, которая выполняется, и большая часть ее в порядке, но я делаю вызовы API, где я извлекаю данные, и я использую асинхронную задачу для этого, чтобы иметь возможность использовать «ожидание», чтобы код подождите, пока эта конкретная часть не будет выполнена, а затем двигайтесь дальше:
private async void MyMethod(PimData pimData, IEnumerable<ProductMeasurements> measurements)
{
try
{
// alot of logic but most relevant part
await Task.WhenAll(ExecuteMeasurmentAndChartLogic(pimData.ProductNumber, entity));
await Task.WhenAll(resourceImportManager.HandleEntityImageFiles(pimData.ProductType + pimData.ProductSize,SwepImageType.Png, ResourceFileTypes.ThreeD, entity, LinkTypeId.ProductResource));
await Task.WhenAll(resourceImportManager.HandleEntityImageFiles(pimData.ProductSketch, SwepImageType.Png, ResourceFileTypes.Sketch, entity, LinkTypeId.ProductResource));
}
catch (Exception e)
{
// logg
}
}
Проблемы:
1 Для начала цикл завершается до завершения всего кода
2 Вторая проблема заключается в том, что я получаю сообщение «Задача была отменена» во многих вызовах API.
3 И в-третьих, как упоминалось выше, код не ждет полного выполнения каждого метода.
Я не могу заставить его выполнить все в методе ExecuteMeasurmentAndChartLogic(), прежде чем перейти к следующему шагу.
Это дает мне следующие проблемы (больше проблем):
В этом методе я создаю элемент и добавляю его в БД, и этот элемент нуждается в дополнительной информации, которую я получаю из вызова API, который выполняется внутри ExecuteMeasurmentAndChartLogic(), но проблема в том, что несколько элементов создаются и должны ждать остальные данные, которые мне не нужны.
ПРИМЕЧАНИЕ. Я знаю, что создание элемента и добавление в базу данных до того, как будут получены все данные, не является лучшей практикой, но я интегрируюсь с PIM, и этот процесс является деликатным
Я хочу, чтобы работало несколько потоков, но в то же время я хочу, чтобы полная логика выполнялась для каждого элемента, прежде чем переходить к следующему методу.
Уточнить:
Работает несколько предметов
Каждый элемент обрабатывает ВСЮ логику, которую ему нужно обработать, прежде чем перейти к следующей части кода. Обычно это делается с помощью await.
В приведенном выше коде метод resourceImportManager() выполняется до завершения ExecuteMeasurmentAndChartLogic(). чего я не хочу.
Вместо Parallel.ForEach я использовал:
Task task1 = Task.Factory.StartNew(() => MyMethod(data, measurements));
Task.WaitAll(task1);
но это не сильно помогло
Довольно новичок в этом и не смог понять, где я делаю это неправильно.
РЕДАКТИРОВАТЬ: Обновлены проблемы с этим
РЕДАКТИРОВАТЬ: так выглядит ExecuteMeasurmentAndChartLogic():
public async Task ExecuteMeasurmentAndChartLogic(string productNumber, Entity entity)
{
try
{
GrafGeneratorManager grafManager = new GrafGeneratorManager();
var graphMeasurmentList = await MeasurmentHandler.GetMeasurments(productNumber);
if (graphMeasurmentList.Count == 0) return;
var chart = await grafManager.GenerateChart(500, 950, SystemColors.Window, ChartColorPalette.EarthTones,
"legend", graphMeasurmentList);
await AddChartsAndAddToXpc(chart, entity, productNumber);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
РЕДАКТИРОВАТЬ: Предыстория этого: я звоню в API, чтобы получить много данных. Для каждого элемента в этих данных мне нужно сделать вызов API и получить данные, которые я применяю к элементу.
После прочтения комментариев, которые также заставили меня задуматься по-другому. Возможно, я могу перебрать все свои элементы и выполнить для них небольшую логику, добавить URL-адрес в список задач и создать отдельную задачу, которая выполняет это один за другим.
буду держать это в курсе
MyMethod
являетсяasync void
, а неasync Task
? - person GWigWam   schedule 28.07.2017resourceImportManager.HandleEntityImageFiles
. Для начала похоже, что вы используете WaitAll и WhenAll для отдельных задач. Кроме того, асинхронная пустота — это большое нет-нет, вы, вероятно, могли бы изменитьParallel.ForEach
наTask.WhenAll
с помощью некоторого рефакторинга. - person Peter Bons   schedule 28.07.2017Parallel.ForEach
, либо он привязан к вводу-выводу, и в этом случае вам следует использовать асинхронный режим. - person Tim Rogers   schedule 28.07.2017await HandleEntityImageFiles
вместо awaitawait Task.WhenAll(HandleEntityImageFiles)
, так как он возвращает одну задачу. Теперь вы можете запускать несколько задач одновременно, но тогда я ожидаю что-то вродеawait Task.WhenAll(ExecuteMeasurmentAndChartLogic(pimData.ProductNumber, entity), resourceImportManager.HandleEntityImageFiles(xxx), resourceImportManager.HandleEntityImageFiles(yyy);
- person Peter Bons   schedule 28.07.2017