Любой способ получить доступ к результатам параллельных задач, как только они будут выполнены? - PullRequest
0 голосов
/ 03 мая 2020

В настоящее время я выполняю несколько задач параллельно и помещаю результаты в список, из которого я использую данные. Я хочу выполнить все свои задачи параллельно, но как только одна из задач будет выполнена для прямого доступа к данным, это данные

Вот мой текущий код:

await Task.Run(async () =>
            {
                Parallel.For(0, k, i =>
                {
                    var tt = Sites.oneNews(cat, sites[i]);
                    results.Add(tt.Result);
                });
            });

Я могу ' не жди их всех до конца sh, потому что некоторые из них занимают слишком много времени. Мне нужно получить доступ к результату, как только он вернется индивидуально

Ответы [ 4 ]

1 голос
/ 03 мая 2020

Просто сделайте results поточно-ориентированной коллекцией производителя-потребителя, такой как BlockingCollection . У него есть GetConsumingEnumerable метод, который возвращает IEnumerable, который выдаст элемент, как только другая часть кода добавит его в коллекцию.

var results = new BlockingCollection<Result>();

async Task ProducerAsync()
{
  await Task.Run(() => // I removed the async here as it was not needed
  {
    Parallel.For(0, k, i =>
    {
      var tt = Sites.oneNews(cat, sites[i]);
      results.Add(tt.Result);
    });
  });

  results.CompleteAdding(); // notify any enumerable that no more items will arrive
}

void Consumer()
{
  foreach (var result in results.GetConsumingEnumerable())
  {
    // each result will arrive here as soon as it becomes available
  }
}

Или если вы хотите использовать результаты в том же методе, где они производятся (обратите внимание, что я переместил вызов на CompleteAdding внутри Task.Run):

var results = new BlockingCollection<Result>();

var producerTask = Task.Run(() => // I removed the async here as it was not needed
{
  Parallel.For(0, k, i =>
  {
    var tt = Sites.oneNews(cat, sites[i]);
    results.Add(tt.Result);
  });

  results.CompleteAdding(); // notify any enumerable that no more items will arrive
});

foreach (var result in results.GetConsumingEnumerable())
{
  // each result will arrive here as soon as it becomes available
}

await producerTask;
1 голос
/ 03 мая 2020

Я бы посоветовал вам прочитать эту статью - она ​​помогла мне реализовать общий лог c в одном из моих проектов и также рекомендована документацией do tnet (я также приведу ссылку на C# документация , которая помогла мне найти этот ресурс).

0 голосов
/ 03 мая 2020

Может быть, я неправильно понимаю, но что мешает вам просто вызывать метод из параллели для обработки результатов по мере их поступления? Код как ниже. Мы уже работаем в разных потоках, поэтому обработка одного набора результатов не будет блокировать обработку следующего набора, что и происходит в Consumer @ ckuri для l oop, который обрабатывает все результаты в одном потоке. Это имеет значение только в том случае, если работа с ними идет медленно, конечно.

Это кажется настолько тривиальным, что мне интересно, не поняла ли я истинную проблему.

await Task.Run(() =>
{
    Parallel.For(0, k, i =>
    {
        var tt = Sites.oneNews(cat, sites[i]);
        var result = tt.Result;
        results.Add(result);
        // Call a method to handle the results as they arise
        HandleResult(result);
    });
});
0 голосов
/ 03 мая 2020

Не зная точно, в каком контексте вы используете этот код, я могу сказать, что вам не нужно использовать ключевое слово asyn c, так как выполняемая вами операция не является асинхронной. В любом случае, если вам нужно обработать какое-либо событие с измененной коллекцией, вы можете использовать ObservableCollection, прослушать любое событие CollectionChanged и обработать добавляемый tt.Result. Но имейте в виду, что, поскольку вы используете параллелизм, это означает, что, поскольку ваш код не асинхронный, то, вероятно, каждый l oop будет заканчиваться sh в один и тот же момент времени (в зависимости от интенсивности операции). Опять же, я не знаю точного контекста, поэтому не могу сказать больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...