Перерва паралельно.


111

Як вийти з паралелі.для циклу?

У мене є досить складна заява, яка виглядає наступним чином:

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
    new Action<ColorIndexHolder>((ColorIndexHolder Element) =>
    {
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
        {
            Found = true;
            break;
        }
    }));

Використовуючи паралельний клас, я можу далеко оптимізувати цей процес. Однак; Я не можу зрозуміти, як розірвати паралельну петлю? Оператор break;містить наступну синтаксичну помилку:

Немає певних циклів, з яких можна розірвати чи продовжити


1
Чи очікуєте ви, що ВСІ паралельні екземпляри циклу одночасно ламаються?
n8wrl

Відповіді:


185

Використовуйте ParallelLoopState.Breakметод:

 Parallel.ForEach(list,
    (i, state) =>
    {
       state.Break();
    });

Або у вашому випадку:

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
    new Action<ColorIndexHolder, ParallelLoopState>((ColorIndexHolder Element, ParallelLoopState state) =>
    {
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
        {
            Found = true;
            state.Break();
        }
    }));

точно. збирався опублікувати це сам.
Mare Infinitus

1
Розмірковуючи послідовний цикл foreach, гарантується, що предмети перед елементом, які з будь-якої причини спричинили розрив, будуть оброблені. Що з паралельним.ForEach, де порядок елементів не обов'язково повинен бути порядком, в якому вони обробляються? Чи гарантується також, що всі елементи в IENumerable <...> перед тим, що викликає state.Break (), обробляються, а ті, що надходять після нього, не є? Хоча першого можна якось досягти, я не бачу, як би це взагалі було можливо.
Хендрік Візе

4
@Hendrik Wiese: Документи кажуть: Calling the Break method informs the for operation that iterations after the current one don't have to execute. However, all iterations before the current one will still have to be executed if they haven't already.іthere is no guarantee that iterations after the current one will definitely not execute.
Тюдор,

2
тому тоді було state.Stop()б доцільніше надійно досягти очікуваних результатів, про що Майк Перренуд та MBentley згадували нижче
xtreampb

44

Ви робите це, зателефонувавши за допомогою перевантаження Parallel.Forабо, Parallel.ForEachщо переходить у стан циклу, а потім виклику ParallelLoopState.BreakабоParallelLoopState.Stop . Основна відмінність полягає в тому, наскільки швидко обриваються речі Break(), цикл обробляє всі елементи з попереднім "індексом", ніж поточний. ЗStop() , він вийде якнайшвидше.

Докладні відомості див. У розділі Як зупинити або вирвати з паралелі. Для циклу .


3
+1, схоже на те, що деякі з нас мають таку саму відповідь :) - о, і я повернувся на цю людину з коментарем.
Майк Перренод

Дякую за це пояснення. Чи знаєте ви, коли викликається або перерва, або зупинка, чи буває так, що завершені в даний час ітерації виконуються або це зупиняє ітерації в середині шляху через виконання?
CeejeeB

1
@CeejeeB Наразі виконання операцій завершено.
Рід Копсі

12

Що вам слід скористатись Any, а не цикл foreach:

bool Found = ColorIndex.AsEnumerable().AsParallel()
    .Any(Element => Element.StartIndex <= I 
      && Element.StartIndex + Element.Length >= I);

Any досить розумний, щоб зупинитися, як тільки дізнається, що результат повинен бути правдивим.


10

LoopState, безумовно, чудова відповідь. Я виявив, що в попередніх відповідях було стільки інших матеріалів, що важко було побачити відповідь, тому ось простий випадок:

using System.Threading.Tasks;

Parallel.ForEach(SomeTable.Rows(), (row, loopState) =>
{
    if (row.Value == testValue)
    {
        loopState.Stop();  // Stop the ForEach!
    }       
    // else do some other stuff here.
});

5

Просто використовуйте те, loopStateщо може бути надано.

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),  
    new Action<ColorIndexHolder>((Element, loopState) => { 
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I) { 
            loopState.Stop();
        }     
})); 

Подивіться для прикладу цю статтю MSDN .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.