Task Parallel Library – переривання паралельних циклів

Доброго ранку, ця стаття буде продовженням до попередньої, в якій розповідалось про використання паралельних методів For та ForEach.

В нашому розпорядженні є кілька перевантажень цих методів, які нам рано чи пізно прийдеться використовувати в наших програмах. Наприклад є така ситуація, в якій потрібно зупинити цикл при певних умовах, то в стандартних реалізаціях послідовних циклів використовується оператор break, який моментально перериває цикл. Наведу приклад:

static void Main(string[] args)
{
    Int32[] array = new Int32[100000];
    Random r =new Random();
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = r.Next(array.Length);
        if (i > 50) break;
    }
}

В даному циклі стоїть умова, при якій цикл закінчує своє виконання. Якщо ми використовуємо метод Parallel.For, то ми маємо використати його перевантажену версію, яка приймає делегат Action<Int32, ParallelLoopState>. Крім цього, у нашому розпорядженні є два екземплярні методи класу ParallelLoopState: Break та Stop. Виклик першого методу спричинить завершення циклу тільки тоді, коли всі паралельні операції в даній ітерації будуть завершені, коли виклик методу Stop зупинить цикл як тільки буде мати можливість:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace ParallelForForEachBreak
{
    class Program
    {
        static void Main(string[] args)
        {
             Int32[] array = new Int32[100000];
             Random r =new Random();
             for (int i = 0; i < array.Length; i++)
             {
                  array[i] = r.Next(array.Length);
             }
             ConcurrentStack<Int32> result = new ConcurrentStack<Int32>();
             Parallel.For(0, array.Length, (i, state) =>
             {
                 result.Push(array[i]);
                 if (i / 5 > 100)
                 {
                     state.Break();
                     Console.WriteLine("Iteration was breaked at {0} ", i);
                 }
              });
        }
    }
}

В цьому коді спочатку я заповнив масив довільними значеннями, після чого викликав метод For, в який передав значення, з якого буде починатись ітерація (значення лічильника i), число, до якого буде працювати паралельний цикл, та екземпляр делегату Action<Int32, ParallelLoopState> у вигляді анонімного методу. Паралельний цикл почав ці значення заштовхувати в ConcurrentStack, який представляє собою потокобезпечний стек. Використовуючи екземпляр класу ParallelLoopState я викликаю метод Break, який в свою чергу зупинить виконання паралельного циклу.

Тепер та сама ітерація, але з використанням методу Stop:

Parallel.For(0, array.Length, (i, state) =>
{
    result.Push(array[i]);
    if (i / 5 > 100)
    {
        state.Stop();
        Console.WriteLine("Iteration was stopped at {0} ", i);
    }
});

В цьому випадку, на відміну від першого, цикл зупиниться швидко, навіть якщо кілька потоків почали вже виконувати операцію. Потрібно зрозуміти, що метод Stop відрізняється від Break тим, що другий, дасть можливість завершити операції, які є вже є запущені.

На сайті MSDN пише, що цикл може буде запущений певний проміжок часу після виклику операції Stop або Break. Тобто на екрані може бути виведений такий результат:

clip_image002

Таку саму конструкцію завершення циклів ми можемо використовувати у методі ForEach.

Якщо виникнуть якісь запитання та зауваження, залишайте будь-ласка коментарі. Всього найкращого!

Advertisements

, , , ,

  1. #1 by ZuTa on July 26, 2011 - 08:21

    то, що краще використовувати? метод Break чи Stop?
    різниця між ними тільки в тому що Break дає можливість закінчити вже розпочаті дії ?

  2. #2 by Serhiy Shumakov on July 26, 2011 - 15:09

    На мою думку краще використовувати Break. Цей метод дасть змогу завершити паралельні ітерації, які мають номер (індекс) меньший ніж та, що його викликала. Наприклад ітерація №9 викликає Break, хоча ітерації № 3,4,5 ще не завершились. В цьому випадку вони будуть завершені.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: