Параллельный шаблон для тестирования нескольких предметов и, возможно, освобождения под залог - PullRequest
3 голосов
/ 11 января 2011

У меня есть проблема, я думаю, она хорошо подходит для параллельной работы, но я не уверен, как именно это выразить в C #.Обычно в этой программе я буду запускать дорогостоящий тест на нескольких объектах.Я проверяю, чтобы убедиться, что я могу идти вперед, поэтому мне нужно знать, если какой-либо из этих тестов не пройдет.Тем не менее, если какой-либо тест не пройден, весь процесс не пройден, и вся функция должна выйти из строя.В псевдокоде:

...
var guys = getGuysToProcess().ToList();
foreach (myGuys guy in guys) {
    if (!guy.TestForPossibleBadness())
      return false;
}

Какой шаблон в C # лучше всего позволит мне выразить это и протестировать их все параллельно?Если что-то из этого не получится, остальные тесты должны быть прекращены, поскольку их результат не имеет значения.

Ответы [ 3 ]

2 голосов
/ 11 января 2011

Поскольку вы упоминаете TPL, у вас также есть PLINQ:

// untested
bool ok = getGuysToProcess().AsParallel().All(g => !g.TestForPossibleBadness());

Как указывает @mquan, это может быть не самым эффективным.Я предполагаю, что следующее может быть быстрее (но я не уверен на 100%):

// untested
bool ok = ! getGuysToProcess().AsParallel().Any(g => g.TestForPossibleBadness());
0 голосов
/ 11 января 2011

Завершающей частью может быть либо игнорирование задач, впоследствии, либо, если возможно, использование CancelationToken, как упомянуто mquander.

Позвольте мне выкинуть какой-нибудь грязный непроверенный псевдоиш-код:

var guyTask = new List<Task<bool>>();
foreach(var guy in guys){
  guyTask.Add(Task.Factory.StartNew(()=>guy.TestForPossibleBadness());
}
var guyTaskArr = guyTask.ToArray();
var running = true;
while(true){
  var i = Task.WaitAny(guyTaskArr);
  if (!guyTaskArr[i]))
     foreach(var guy in guyTask){
         if (!guy.IsCompleted || !guy.IsFaulted){
             guy.Cancel();
         }
     }
     return false;
  }else{
     guyTask.Remove(guyTaskArr[i]);
     if (guyTask.Count == 0) return true;
     guyTaskArr = guyTask.ToArray();
  }
}

PLINQ выглядит немного чище ИМХО

0 голосов
/ 11 января 2011

Подход PLINQ будет следующим:

bool isBad = GetGuysToProcess().AsParallel().Any(g => g.TestForPossibleBadness());

Сохраните GetGuysToProcess в виде последовательности, запустите параллельно и найдите первый «плохой».

...