презентация параллельное программирование. Параллельное программирование. Параллельное программирование. Преподаватель Кривошеина А. В
Скачать 115.53 Kb.
|
Параллельное программирование.Преподаватель Кривошеина А.В.ЧУО «Колледж бизнеса и права»
Задачи и класс Task
Первый способ :
Task task = new Task(() => Console.WriteLine ("Hello Task!"));task.Start();Второй способ:
Task task = Task.Factory.StartNew(() => Console.WriteLine("Hello Task!"));Третий способ:
Task task = Task.Run(() => Console.WriteLine("Hello Task!"));using System; using System.Threading.Tasks; namespace HelloApp { class Program { static void Main(string[] args) { Task task1 = new Task(() => Console.WriteLine("Task1 is executed")); task1.Start(); Task task2 = Task.Factory.StartNew(() => Console.WriteLine("Task2 is executed")); Task task3 = Task.Run(() => Console.WriteLine("Task3 is executed")); Console.ReadLine(); } } } Ожидание задачиusing System; using System.Threading; namespace TaskApp { class Program { static void Main(string[] args) { Task task = new Task(Display); task.Start(); Console.WriteLine("Завершение метода Main"); Console.ReadLine(); } static void Display() { Console.WriteLine("Начало работы метода Display"); Console.WriteLine("Завершение работы метода Display"); } } } консольный вывод может выглядеть следующим образом: Завершение метода Main Начало работы метода Display Завершение работы метода Display Чтобы указать, что метод Main должен подождать до конца выполнения задачи, нам надо использовать метод Wait:static void Main(string[] args) { Task task = new Task(Display); task.Start(); task.Wait(); Console.WriteLine("Завершение метода Main"); Console.ReadLine(); } Свойства класса Task:
Работа с классом Task Вложенные задачиstatic void Main(string[] args) { var outer = Task.Factory.StartNew(() => // внешняя задача { Console.WriteLine("Outer task starting..."); var inner = Task.Factory.StartNew(() => // вложенная задача { Console.WriteLine("Inner task starting..."); Thread.Sleep(2000); Console.WriteLine("Inner task finished."); }); }); outer.Wait(); // ожидаем выполнения внешней задачи Console.WriteLine("End of Main"); Console.ReadLine(); } Если необходимо, чтобы вложенная задача выполнялась вместе с внешней, необходимо использовать значение TaskCreationOptions.AttachedToParent:static void Main(string[] args) { var outer = Task.Factory.StartNew(() => // внешняя задача { Console.WriteLine("Outer task starting..."); var inner = Task.Factory.StartNew(() => // вложенная задача { Console.WriteLine("Inner task starting..."); Thread.Sleep(2000); Console.WriteLine("Inner task finished."); }, TaskCreationOptions.AttachedToParent); }); outer.Wait(); // ожидаем выполнения внешней задачи Console.WriteLine("End of Main"); Console.ReadLine(); } Task[] tasks1 = new Task[3] { new Task(() => Console.WriteLine("First Task")), new Task(() => Console.WriteLine("Second Task")), new Task(() => Console.WriteLine("Third Task")) }; // запуск задач в массиве foreach (var t in tasks1) t.Start(); Также как и с потоками, мы можем создать и запустить массив задач. Можно определить все задачи в массиве непосредственно через объект Task: Task[] tasks2 = new Task[3]; int j = 1; for (int i = 0; i < tasks2.Length; i++) tasks2[i] = Task.Factory.StartNew(() => Console.WriteLine($"Task {j++}")); Либо также можно использовать методы Task.Factory.StartNew или Task.Run и сразу запускать все задачи: Но в любом случае мы опять же можем столкнуться с тем, что все задачи из массива могут завершиться после того, как отработает метод Main, в котором запускаются эти задачи. Например:static void Main(string[ ] args) { Task[ ] tasks1 = new Task[3] { new Task(() => Console.WriteLine("First Task")), new Task(() => Console.WriteLine("Second Task")), new Task(() => Console.WriteLine("Third Task")) }; foreach (var t in tasks1) t.Start(); Task[] tasks2 = new Task[3]; int j = 1; for (int i = 0; i < tasks2.Length; i++) tasks2[i] = Task.Factory.StartNew(() => Console.WriteLine($"Task {j++}")); Console.WriteLine("Завершение метода Main"); Console.ReadLine(); } Один из возможных консольных выводов данной программы:Second Task Task 1 Завершение метода Main Third Task Task 3 First Task Task 2 Если необходимо выполнять некоторый код лишь после того, как все задачи из массива завершатся, то применяется метод Task.WaitAll(tasks):static void Main(string[] args) { Task[] tasks1 = new Task[3] { new Task(() => Console.WriteLine("First Task")), new Task(() => Console.WriteLine("Second Task")), new Task(() => Console.WriteLine("Third Task")) }; foreach (var t in tasks1) t.Start(); Task.WaitAll(tasks1); // ожидаем завершения задач Console.WriteLine("Завершение метода Main"); Console.ReadLine(); } Возвращение результатов из задач
class Program { static void Main(string[] args) { Task task1.Start(); Console.WriteLine($"Факториал числа 5 равен {task1.Result}"); Task { return new Book { Title = "Война и мир", Author = "Л. Толстой" }; }); task2.Start(); Book b = task2.Result; // ожидаем получение результата Console.WriteLine($"Название книги: {b.Title}, автор: {b.Author}"); Console.ReadLine(); } static int Factorial(int x) { int result = 1; for (int i = 1; i <= x; i++) { result *= i; } return result; } } public class Book { public string Title { get; set; } public string Author { get; set; } }
Задачи продолжения
using System; using System.Threading; using System.Threading.Tasks; namespace TaskApp { class Program { static void Main(string[] args) { Task task1 = new Task(()=>{ Console.WriteLine($"Id задачи: {Task.CurrentId}"); }); // задача продолжения Task task2 = task1.ContinueWith(Display); task1.Start(); // ждем окончания второй задачи task2.Wait(); Console.WriteLine("Выполняется работа метода Main"); Console.ReadLine(); } static void Display(Task t) { Console.WriteLine($"Id задачи: {Task.CurrentId}"); Console.WriteLine($"Id предыдущей задачи: {t.Id}"); Thread.Sleep(3000); } } } И после завершения задачи task1 сразу будет вызываться задача task2. Также мы можем передавать конкретный результат работы предыдущей задачи:using System; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace HelloApp { class Program { static void Main(string[] args) { Task // задача продолжения Task task2 = task1.ContinueWith(sum => Display(sum.Result)); task1.Start(); // ждем окончания второй задачи task2.Wait(); Console.WriteLine("End of Main"); Console.ReadLine(); } static int Sum(int a, int b) => a + b; static void Display(int sum) { Console.WriteLine($"Sum: {sum}"); } } } Подобным образом можно построить целую цепочку последовательно выполняющихся задач:static void Main(string[] args) { Task task1 = new Task(()=>{ Console.WriteLine($"Id задачи: {Task.CurrentId}"); }); // задача продолжения Task task2 = task1.ContinueWith(Display); Task task3 = task1.ContinueWith((Task t) => { Console.WriteLine($"Id задачи: {Task.CurrentId}"); }); Task task4 = task2.ContinueWith((Task t) => { Console.WriteLine($"Id задачи: {Task.CurrentId}"); }); task1.Start(); Console.ReadLine(); } static void Display(Task t) { Console.WriteLine($"Id задачи: {Task.CurrentId}"); } |