Томский политехнический университет
Опубликован: 23.01.2013 | Доступ: свободный | Студентов: 1158 / 192 | Длительность: 12:09:00
Лекция 6:

Параллелизм задач

Аннотация: В рамках данной лекции будут рассмотрены следующие вопросы:определение параллелизма задач; создание и запуск задачи; создание вложенных задач; ожидание задач; обработка ошибок в задачах; отмена выполнения заданий; продолжения; продолжения и Task <TResult>; продолжения и дочерние задачи; продолжения предыдущих задач; несколько продолжений одной задачи; планировщики заданий и пользовательский интерфейс.

Введение

Параллелизм задач (task parallelism) - это низкоуровневый подход к распараллеливанию задач с помощью PFX. Классы этого уровня определены в пространстве имен System.Threading.Tasks (Табл. 7.1).

Таблица 7.1. Основные классы пространства имен System.Threading.Task
Класс Описание
Task Представляет асинхронную операцию.
Task <TResult> Представляет асинхронную операцию, которая возвращает значение.
TaskScheduler Объект, обрабатывающий низкоуровневую постановку задач в очередь на потоки.
TaskFactory Для создания объекта Task.
TaskFactory <TResult> Для создания объекта Task, с возвращаемым значением.

Создание и запуск задачи

Как уже писалось в "Введение в асинхронные задачи" задачи можно создавать различными способами. Один из таких способов - это использование лямда-выражения и метода Task.Factory.StartNew():

Task.Factory.StartNew (() => Console.WriteLine ("Hello World!"));
 Результат выполнения программы с использованием класса Task

увеличить изображение
Рис. 7.1. Результат выполнения программы с использованием класса Task

Аналогично, можно было вывести на экран сообщение "Hello World!", вначале создав объект Task, а затем вызвав метод Start():

Task task = new Task (() => Console.Write ("Hello World!"));
task.Start();

Что бы выполнить задачу синхронно (в том же потоке) небходимо вызвать метод RunSynchronously() вместо вызова метода Start():

Task task = new Task (() => Console.Write ("Hello World!"));
task.RunSynchronously()

Класс Task <TResult>, позволяет получить определенный набор данных после завершения выполнения задачи:

Task<int> task = Task.Factory.StartNew< int > (() 
{
int i,c,j;
c=5;
j=5;
i=c+j;
return i;
});
 
   DoSomething();         // Выполнение другой операции асинхронно
   Console.WriteLine("Результат выполнения задачи:"+task.Result);
   Console.ReadLine();
 Результат выполнения программы с использованием класса Task <TResult>

увеличить изображение
Рис. 7.2. Результат выполнения программы с использованием класса Task <TResult>

Создание вложенных задач

Вложенные задача - это экземпляр задачи Task, создаваемый в пользовательском делегате другой задачи. Дочерняя задача - это вложенная задача, создаваемая с помощью параметра AttachedToParent. Задача может создать любое количество дочерних и вложенных задач, ограничиваясь только системными ресурсами. Пример кода, демонстрирующий создание вложенных задач, представлен ниже:

Task parent = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Родительская задача запущена");

                Task.Factory.StartNew(() =>        // Дочерняя задача
                {
                    Console.WriteLine("Дочерняя задача запущена");
                    Thread.SpinWait(5000000);
                    Console.WriteLine("Дочерняя задача выполнена");
                    
                });
            });
            parent.Wait();
            Console.WriteLine("Родительская задача выполнена");
 Результат выполнения программы с использованием дочерних задач

увеличить изображение
Рис. 7.3. Результат выполнения программы с использованием дочерних задач

Наиболее важным моментом при сравнении дочерних и вложенных задач является то, что вложенные задачи по существу не зависят от родительской или внешней задачи, тогда как вложенные дочерние задачи синхронизируются с родительской задачей. Если изменить оператор создания задач так, чтобы использовался параметр AttachedToParent, как показано в следующем примере:

Task parent = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Родительская задача запущена");

                Task.Factory.StartNew(() =>        // Дочерняя задача
                {
                    Console.WriteLine("Дочерняя задача запущена");
                    Thread.SpinWait(5000000);
                    Console.WriteLine("Дочерняя задача выполнена");
                    
                }, TaskCreationOptions.AttachedToParent);
            });
            parent.Wait();
            Console.WriteLine("Родительская задача выполнена");
 Результат выполнения программы с использованием дочерних задач и параметра AttachedToParent

увеличить изображение
Рис. 7.4. Результат выполнения программы с использованием дочерних задач и параметра AttachedToParent
Владимир Каширин
Владимир Каширин

Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010".

При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п.

Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010.