Многопоточное программирование ( часть 1) Лекция 10.

Презентация:



Advertisements
Похожие презентации
ПОТОКИ Начальные сведенияПОТОКИ Начальные сведения.
Advertisements

Модель приложений.NET. Среда платформы Win32, в которой выполняется программа, называется ее процессом. Эта среда состоит из: адресного пространства,
Многопоточное программирование Синхронизация потоков Лекция 11.
ДЕЛЕГАТЫ Лекция 7 1. Зачем нужны делегаты 2 И данные, и код располагаются в памяти компьютера по определенным адресам. Передача адресов данных в C# происходит.
Высокоуровневые методы информатики и программирования Лекция 9 Делегаты.
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
1 Средства асинхронного программирования, Многопоточное программирование, Синхронизация потоков в.Net Наговицына Полина, 444гр Григорьева.
Высокоуровневые методы информатики и программирования Лекция 10 События.
Делегаты Как созданные объекты могут посылать сообщения тем объектам, которые их породили? При программировании под Windows на С и C++ основное средство.
Многопоточное программирование на Java Java Advanced.
Гайдар Магдануров Microsoft.
Введение в разработку многопоточных приложений. Поморгаем int main() { while(true) { EnableLedOne(); DisableLedOne(); }
Многопоточное программирование на Java Java Advanced.
Гайдар Магдануров Microsoft.
ОБЪЕКТНО- ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ (ООП) 1.
МНОГОПОТОЧНОЕ ПРОГРАММИРОВАНИЕ В JAVA Пакеты java.lang java.util.concurrent.
ИТЕРАТОРЫ И LINQ Лекция 1. Интерфейс IEnumerable и IEnumerator Любая коллекция реализует интерфейс IEnumerable. public interface IEnumerable : IEnumerable.
Наследование Наследование – это отношение является между классами. class Person { string first_name; int birth_year;... } class Student : Person { float.
Многопоточное программирование в OpenMP Киреев Сергей ИВМиМГ.
Классы в С#. Перечисления С# Перечисление задает конечное множество возможных значений, которые могут получать объекты класса перечисление. [атрибуты][модификаторы]
Транксрипт:

Многопоточное программирование ( часть 1) Лекция 10

Процесс – выполняющаяся программа ( экземпляр ) Процесс может содержать один или несколько потоков Поток ( нить, thread) – путь выполнения внутри исполняемого приложения При запуске приложения создается и запускается главный поток Любой поток может запускать дополнительные потоки Потоки выполняются параллельно и независимо Завершение процесса – завершение всех его потоков Нет четкой корреляции между потоком операционной системы и управляемым потоком.NET Один поток ОС может обслуживать несколько потоков.NET Многопоточные приложения могут выполнятся и на однопроцессорном компьютере

При грамотном подходе может значительно ускорить работу приложения ( только при многоядерной или много процессорной архитектуре ) Позволяет повысить отзывчивость пользовательского интерфейса ( даже при однопроцессорной архитектуре ) Позволяет ускорить работу приложения за счет одновременного выполнения : долгих удаленных операций ( выполняющихся на других компьютерах ) Например, запрос к базе данных, к сервису или к интернет ресурсу медленных, но мало затратных операций Например, сохранение или чтение с диска Трудности разработки ( дороговизна разработки ) Разбиение и оптимизация программы для многопоточной работы Синхронизация потоков Тестирование Трудности тестирования и отладки Трудно обнаружимые ошибки Невоспроизводимые ошибки Непредсказуемые ошибки При неграмотном подходе может замедлить приложение На создание и поддержание работы потоков тратятся ресурсы

Пространства имен System.Threading System.Threading.Tasks System.ComponentModel ( поток для UI, BackgroundWorker) Класс System.Threading.Thread Методы для работы с потоками Статические члены для текущего потока static Thread Thread.CurrentThread – текущий поток Единица кода для запуска в потоке – метод В отдельном потоке всегда запускается кокой - то метод

Необходимо создать метод, который будет выполнятся новым потоком public static void threadMethod() {…} Создание экземпляра делегата на метод ThreadStart – для запуска потока без параметров ParameterizedThreadStart – для запуска потока с одним параметром ( но параметр object) Создание потока и передача ему делегата на метод Thread thread= new Thread(new ThreadStart(threadMethod)); Start() Запуск потока thread.Start();

Использование делегата ParameterizedThreadStart вместо ThreadStart Передача только 1 параметра, но параметра типа object public static void threadMethod(object o){..} Thread thread = new Thread(new ParameterizedThreadStart(threadMethod)); thread.Start(obj); Другой способ – класс - обертка

Thread Передача параметров Класс обертка

Свойства потока Name Name – имя потока ( удобно использовать для отладки ) ManagedThreadId ManagedThreadId – уникальный ID потока Priority Priority – приоритет потока IsAlive IsAlive – поток запущен и не приостановлен ThreadState ThreadState – состояние потока IsBackground IsBackground – фоновый ли поток IsThreadPoolThread IsThreadPoolThread – принадлежит ли поток пулу потоков CLR Полезные методы и свойства для работы с потоками CurrentThread Thread.CurrentThread – ссылка на текущий поток ( статическое вычислимое свойство ) Sleep() Thread.Sleep() – заставляет поток ожидать указанное время ( статический метод ) Join() thread.Join() – заставляет ожидать текущий поток завершения указанного потока. Abort() thread.Abort() – заставляет аварийно завершить поток

UnstartedUnstarted RunningRunning SuspendSuspend SuspendRequestedSuspendRequested WaitSleepJoinWaitSleepJoin FinishedFinished Abort Requested

Поток завершится при выходе из метода Abort() thread.Abort() – аварийное завершение потока При этом у прерываемого потока возникает исключение ThreadAbortedException Прерываемый поток может обработать исключение ThreadAbortedException, но после этого исключение будут вызвано снова AbortReset() thread.AbortReset() – отмена прерывания потока ( если успеть, пока поток еще аварийно не завершился ) Join() thread.Join() – блокировка текущего потока до завершения другого потока Завершенный поток нельзя запустить снова

Потоки : Потоки переднего плана ( по умолчанию ) Фоновые потоки Процесс не завершится пока есть работающие потоки переднего плана Фоновые потоки при завершении основного потока получают исключение ThreadAbortedException и будут завершены Необходима реализация безопасного завершения фонового потока Установка потока как фонового IsBackground thread.IsBackground = true;

Завершение фонового потока

В среде выполнения уже существует несколько запущенных потоков – пул потоков Количество поток связано с количеством процессоров. При использовании потока из пула потоков нет накладных расходов на создание потока В пуле потоки фоновые Класс ThreadPool – позволяет получить доступ к пулу потоков.NET Постановка задания в очередь Создание экземпляра делегата void WaitCallback(object state ) ThreadPool.QueueUserWorkItem Постановка в очередь ThreadPool.QueueUserWorkItem WaitCallback (new WaitCallback(threadMethod), obj); Переданное задание уже нельзя отменить

Пул потоков

BeginInvoke()EndInvoke() Любой делегат имеет помимо метода для синхронного вызова – Invoke(), методы для асинхронного вызова BeginInvoke(), EndInvoke() Func f = …. IAsyncResult f.BeginInvoke(string s, double d, AsyncCallback callback, object obj) – начинает вызов и передает параметры string, double int f.EndInvoke(IAsyncResult ires) – ожидает завершения и возвращает значение AsyncCallback callback – делегат будет вызван при окончании вычисления

Свойство bool IsComplated – завершено ли вычисление Свойство object AsyncState – позволяет передавать параметры для последующий идентификации вызванного метода

Асинхронный вызов делегата

Простой запуск выполнения действия в Thread Pool Tack - класс для вызова метода, ничего не возвращающего, а Task для возвращающего результат Tresult Start() Запуск таски – Start(). Конструктор – настройка таски void inc() { … } Task t = new Task(inc); t.Start(); Task t = new Task (GetInt); t.Start(); Task.Factory.StartNew Быстрый старт заданий ( рекомендуемый ) Task.Factory.StartNew() Task t = Task.Factory.StartNew(inc); Task t = Task.Factory.StartNew(GetInt); Task t = Task.Factory.StartNew(Add, new object[] { 5,7 } ); Result Получение результата по окончании таски Task - свойство Result int res = t.Result; // если t – Task

ContinueWith Продолжение выполнения ContinueWith(); Метод будет выполняться по завершении таски ( сама таска пойдет на вход методу ) void inc() { … } void a(Task t) { … } Task task = Task.Factory.StartNew(inc); task.ContinueWith(a); Синхронизация тасок Wait() Ожидание завершения таски Wait(); t.Wait(); Task.WaitAll() Ожидание завершения всех тасок Task.WaitAll() Task.WaitAll(task1, task2, task3) Task.WaitAny() Ожидание завершения хотя бы одной тасок Task.WaitAny() Task.WaitAny(task1, task2, task3) Отмена тасок – передача токена отмены CancellationToken

Parallel.For Parallel.For(initvalue, endvalue, Action ); - Выполнение цикла в максимально возможном числе потоков (ThreadPool). В цикле выполняется делегат Action ( который принимает 1 параметр T и, ничего не возвращает ). Числом потоков управляет CLR Parallel.ForEach Parallel.ForEach (IEnumerable, Action ); - Выполнение делегата Action над всеми элементами перечисления в максимально возможном числе потоков. Числом потоков управляет CLR List l = new List (); public void dec(int i) {} Parallel.For(0, 10, dec); Parallel.ForEach (l, dec); Parallel.Invoke Parallel.Invoke(params Action[] actions) – выполнение делегатов в отдельных потоках, если возможно Parallel.Invoke(Print, PrintToScreen, SendTo , () => Console.WriteLine(" Печатаем ")); ParallelOptions Класс ParallelOptions может использоваться для подстройки операций Parallel MaxDegreeOfParallelism MaxDegreeOfParallelism – ограничивает максимально число одновременно выполняющихся задач в классом Parallel. CancellationToken CancellationToken – позволяет отменять задания, выполняющиеся классом Parallel

Parallel Task

Потоки выполняются параллельно и независимо. Нельзя предсказать очередность выполнения блоков кода потоками. static void Main() { Thread t = new Thread(Write1); t.Start(); while (true) Console.Write("-"); // Все время печатать '-' } static void Write1() { while (true) Console.Write("1"); // Все время печатать '1' }

У каждого потока свой стек локальных переменных. Они независимые. static void Main() { new Thread(Go).Start(); // Выполнить Go() в новом потоке Go(); // Выполнить Go() в главном потоке } static void Go() { // Определяем и используем локальную переменную 'cycles' for (int cycles = 0; cycles < 5; cycles++) Console.Write('+'); }

Вместе с тем потоки разделяют данные, относящиеся к тому же экземпляру объекта class TestClass { bool done = false; public void Go() { if (!done) { done = true; Console.WriteLine("Done"); } } } class ThreadTest { static void Main() { TestClass testClass = new TestClass(); new Thread(testClass.Go).Start(); testClass.Go(); }

class Increment { decimal l = 0; public void inc() { for (int i = 0; i < ; ++i) l = l + 1; Console.WriteLine(l); } } class Program { static void Main(string[] args) { Increment i = new Increment (); for (int j = 0; j < 10; ++j) new Thread(i.inc).Start(); } }

Потоки выполняются параллельно и независимо. Нельзя предсказать какой поток отработает быстрее. У каждого потока свой собственный стек. Собственные неразделяемые локальные переменные Потоки разделяют нелокальные переменные, доступные им по области видимости Операции неатомарные