1 Средства асинхронного программирования, Многопоточное программирование, Синхронизация потоков в.Net Наговицына Полина, 444гр Григорьева Елена, 444гр
2 Потоки и работа с потоками Для разделения различных выполняемых приложений в операционных системах используются процессы Потоки являются основными элементами, для которых операционная система выделяет время процессора Внутри процесса может выполняться более одного потока
3 Каждый поток поддерживает обработчик исключений планируемый приоритет набор структур, используемых системой для сохранения контекста потока во время его планирования
4 Среда.NET Framework разделяет процесс операционной системы на несколько подпроцессов (доменов приложения) Домены приложения представлены классом System.AppDomain В домене приложения в неуправляемом процессе может быть запущен один (или более) управляемый поток (представленный классом System.Threading.Thread)
При создании нового экземпляра объекта Thread создаются новые управляемые потоки. В качестве параметра конструктор Thread берет делегат ThreadStart, который создает оболочку метода, вызываемого новым объектом Thread при вызове Thread.Start. using System; using System.Threading; public class ServerClass { public void InstanceMethod() //Метод, который будет вызван при создании потока { Console.WriteLine("ServerClass.InstanceMethod is running on another thread."); Thread.Sleep(3000); //Пауза для более наглядного разделения потоков Console.WriteLine("The instance method called by the worker thread has ended."); } public class Simple { public static int Main(String[] args) { Console.WriteLine("Thread Simple Sample"); ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after starting the new InstanceCaller thread."); }
6 Достоинства многопоточности Использование более одного потока является наиболее мощным средством для увеличения быстроты ответа системы на действия пользователя средством обработки данных, необходимых для одновременного выполнения задачи.
7 Для выполнения следующих задач в домене приложения необходимо использовать несколько потоков: Взаимодействие по сети с веб-сервером и базой данных. Выполнение операций, занимающих много времени. Разделение задач по приоритетам. Например, поток с высоким приоритетом отвечает за срочные задачи, с низким приоритетом за все остальные. Сохранение возможности ответа для интерфейса пользователя при выделении времени для фоновой задачи.
8 Недостатки многопоточности 1.Меньше потоков – меньше количество используемых ресурсов системы 2.При использовании потоков необходимо учитывать требования к ресурсам и возможность возникновения ошибок при разработке приложения
9 Существуют следующие требования к ресурсам. Память, используемая системой для обработки контекстных данных, необходимых в процессах, объектах AppDomain и потоках. Поэтому количество создаваемых процессов, объектов AppDomain и потоков ограничено объемом доступной памяти. Время процессора, используемое для отслеживания количества потоков. Если количество потоков велико, большинство из них не будет работать должным образом. Если большинство текущих потоков находится в одном процессе, потоки других процессов планируются реже. Контроль выполнения кода с большим количеством потоков достаточно сложен и может являться причиной ошибок. При уничтожении потоков необходимо учитывать возможные проблемы и предусмотреть способы их решения.
10 3. При совместном доступе к ресурсам могут возникать конфликты. Для их предотвращения нужно синхронизировать или контролировать доступ к общим ресурсам (иначе зависание и конкуренция)
11 Ресурсы, требующие синхронизации: системные ресурсы (последовательные порты); ресурсы, используемые несколькими процессами (дескрипторы файлов); ресурсы отдельного домена приложения (глобальные, статические поля или поля экземпляров), к которым обращаются несколько потоков.
12 Синхронизация данных для многопоточности Класс, члены которого защищены от прерываний одним потоком операций другого, называется потокобезопасным. Существует несколько способов синхронизации доступа к статическим членам и членам экземпляров.
13 Синхронизованные контексты. Для включения простой автоматической синхронизации объектов ContextBoundObject можно воспользоваться атрибутом SynchronizationAttribute. Синхронизованное свойство. Несколько классов, например Hashtable и Queue, содержат свойство Synchronized, которое возвращает потокобезопасную обертку для экземпляра класса. Синхронизованные области кода. Для синхронизации только требуемых блоков кода в целях улучшения производительности можно воспользоваться классом Monitor. Синхронизация вручную. Для создания собственных механизмов синхронизации можно использовать различные синхронизирующие объекты.
14 КатегорияГлобаль ные поля Статичес кие поля Статичес кие методы Поля экземпля ров Методы экземпля ров Определен ные блоки кода Без синхрони зации Нет Синхрони зованный контекст Нет ДаНет Синхрони зованные области кода Нет Только если помечены НетТолько если помечены Синхрони зация вручную Вручную
15 1. Без синхронизации Этот вариант используется по умолчанию для объектов. Любой поток может обратиться к любому методу или полю в любое время. К этим объектам может обращаться только один поток. 2. Синхронизованный контекст Для синхронизации всех полей и методов экземпляров можно воспользоваться атрибутом SynchronizationAttribute любого объекта ContextBoundObject. Все объекты в одном контекстном домене имеют одинаковую блокировку. Доступ к методам и полям предоставляется нескольким потокам, но только один из них может обращаться к методам или полям одновременно.
16 3. Синхронизованные области кода Monitor или зарезервированное слово компилятора (синхронизация) блоков кода методов экземпляров статических методов Данная поддержка не распространяется на синхронизованные статические поля.
17 Класс Monitor поддерживает следующие виды синхронизации блоков кода. Синхронизованные методы экземпляров. В случае методов экземпляров для синхронизации служит текущий объект (зарезервированное слово this в C# или зарезервированное слово Me в Visual Basic). Синхронизованные статические методы. В случае статических методов для синхронизации используется класс.
18 Visual Basic, C#: создание блоков кода с помощью определенного зарезервированного слова языка. Создаваемый в результате этого код попытается установить блокировку при выполнении кода. Если блокировка уже установлена, код не будет выполняться до тех пор, пока блокировка не будет доступна. Блокировка снимается при завершении работы кода в синхронизованном блоке кода.
19 Синхронизованные методы экземпляров. В случае методов экземпляров для синхронизации служит текущий объект (зарезервированное слово this в C# или зарезервированное слово Me в Visual Basic). Синхронизованные статические методы. В случае статических методов для синхронизации используется класс.
20 При написании многопотокового приложения может понадобиться синхронизация отдельных потоков с другими частями программы. Синхронизация является компромиссом между неструктурированной природой многопотокового программирования и структурированным порядком синхронной обработки. Синхронизация используется в следующих случаях. Для явного контроля порядка выполнения кода, если задания должны выполняться в определенной последовательности или Для предотвращения проблем, возникающих при использовании одного ресурса одновременно двумя потоками.
21 Использование событий распространенный способ синхронизации многопотокового приложения. В этом случае каждый поток создает события, чтобы сообщить свое состояние главной программе или другим потокам. Остальные части приложения, находящиеся вне потока, создавшего событие, обрабатывают это событие и действуют в соответствии с полученной информацией. Примечание. Когда один объект создает событие для другого, обработчик события будет выполняться в том же потоке, в котором выполнился оператор RaiseEvent. Поэтому, если обработчик событий обращается к общим данным, он сам должен использовать синхронизацию, если эти данные в то же время используются другим потоком.
22 Алгоритмы синхронизации Существуют два подхода к синхронизации Опрос. Циклически проверяется статус асинхронного вызова. Опрос является наименее эффективным способом управления потоками, поскольку он занимает ресурсы, постоянно проверяя состояние различных свойств потока. Использование синхронизирующих объектов.
23 При опросе может использоваться свойство IsAlive для проверки существования потока. Свойство ThreadState используется, чтобы получить более подробные сведения о состоянии потока. Поскольку в каждый момент времени потоки могут иметь несколько состояний, значение свойства ThreadState может быть сочетанием значений из перечисления System.Threading.Threadstate. Поэтому при опросе следует тщательно проверять все состояния потока, имеющие отношение к решаемой задаче. Например, если состояние потока показывает, что поток не выполняется, возможно, он завершен. С другой стороны, поток может быть приостановлен или находиться в режиме ожидания.
24 Ожидание завершения потока Метод Thread.Join удобен для определения, завершен ли текущий поток, перед началом следующего задания. Метод Join ожидает завершения потока в течение заданного промежутка времени.
25
26 Асинхронная модель программирования В синхронной модели программирования вызывающий компонент блокируется, пока вызванный интерфейс не закончит обработку запроса и не вернет управление. Асинхронная модель программирования позволяет компонентам отправлять сообщения другим компонентам и продолжать работу, не ожидая немедленного ответа. В приложении на основе асинхронных процессов «долгоиграющие» операции откладываются или выносятся в отдельный процесс.
27.NET Framework позволяет вызывать асинхронно любой метод. Определите делегат с той же подписью, что и у вызываемого метода. Общеязыковая среда выполнения автоматически определяет для этого делегата методы BeginInvoke и EndInvoke с соответствующими подписями.
28 public class AsyncDemo { // The method to be executed asynchronously. public string TestMethod(int callDuration, out int threadId) { Console.WriteLine("Test method begins."); Thread.Sleep(callDuration); threadId = AppDomain.GetCurrentThreadId(); return "MyCallTime was " + callDuration.ToString(); } } // The delegate must have the same signature as the method // you want to call asynchronously. public delegate string AsyncDelegate(int callDuration, out int threadId);
29 Шаблон разработки для асинхронного программирования Асинхронная модель основная технология в.NET Framework. Она представляет собой эффективную модель управления асинхронными операциями и согласованную модель программирования
30 Основные идеи шаблона разработки для асинхронного программирования : Вызывающий объект решает, должен ли быть данный конкретный вызов асинхронным. Вызываемый объект выполняет дополнительное программирование для поддержки асинхронного режима своими клиентами, но этот шаг необязательный. Инфраструктура общеязыковой среды выполнения ответственна за обработку различий между характеристиками вызывающего и вызываемого объектов. Вызванный объект может выбрать явную поддержку асинхронного режима работы либо потому, что он может реализовать асинхронный режим более эффективно, чем базовая архитектура, либо в связи с решением о поддержке только асинхронного режима работы, принятого вызывающим объектом. Однако рекомендуется, чтобы такие вызываемые объекты соответствовали шаблону разработки для асинхронного программирования для реализации асинхронных операций. Компилятор создает для асинхронных делегатов подписи метода безопасных типов для BeginInvoke и EndInvoke..NET Framework предоставляет службы, необходимые для поддержки модели асинхронного программирования. Ниже приведен примерный неполный список таких служб. –Примитивы синхронизации, такие как мониторы и блокировки для чтения и записи. –Потоки и группы потоков. –Конструкторы синхронизации, такие как контейнеры, поддерживающие ожидание в объектах. –Элементы взаимодействия с базовой инфраструктурой, такие как объекты IМessage и группы потоков.
31 Этот шаблон разбивает синхронный вызов на составляющие части: начальная операция, конечная операция и результирующий объект.
32 Поддержка асинхронных вызовов в.NET позволяет вызывать и исполнять методы, не прерывая исполнение основной программы. Асинхронные вызовы удобны в ситуациях, когда исполнение метода занимает слишком много времени, чтобы ожидать его завершения Возможность продолжать исполнение, не дожидаясь завершения вызванных методов, способствует повышению быстродействия приложений.
33 При асинхронном управлении клиент отправляет запрос и продолжает выполнение других задач. Сервис обрабатывает запрос и уведомляет клиента о завершении обработки. При этом клиент не приостанавливает работу и способен выполнять другие действия, не связанные с данной операцией, пока сервис обрабатывает его запрос. Общее управление не передается от вызывающего объекта вызываемому. Это означает, что вызывающий объект должен эффективно управлять целостностью своих данных, к которым могут обратиться одновременнонесколько объектов, и координировать доступ к общим ресурсам.
34 Асинхронный метод исполняется одновременно с основной программой, пока не встретится - обратный вызов, - блокировка, - либо не начнется опрос - или не потребуется дождаться завершения другого метода.
35 В.NET асинхронные методы применяются при реализации: Ввод-вывод в файлы, потоки Работа в сети: HTTP, TCP Удаленные каналы (HTTP, TCP) и прокси Веб-службы XML, создаваемые с помощью ASP.NET Web Forms ASP.NET Message Queuing с использованием класса MessageQueue Асинхронные делегаты
36 Асинхронные методы реализуют с применением: обратных вызовов делегаты обратного вызова передают перед началом асинхронных вызовов; проверки завершения чтобы определить, завершена ли асинхронная процедура, проверяют свойство lAsyncResult.IsCompleted; методов Beginlnvoke, Endlnvoke позволяют немедленно завершить операцию; методов Beginlnvoke, WaitHandle, Endlnvoke управляют ожиданием на объекте lAsync Result
37 Простейшим способом асинхронного выполнения метода является его запуск с помощью BeginInvoke, выполнение каких-либо операций в основном потоке и вызов после этого метода EndInvoke. EndInvoke не возвращается до тех пор, пока не будет завершен асинхронный вызов.
38 Метод BeginInvoke используется для инициирования асинхронного вызова. Он имеет те же параметры, что и метод, который нужно исполнить асинхронно, плюс два дополнительных параметра, которые будут описаны позднее. Возврат BeginInvoke происходит немедленно, не дожидаясь завершения асинхронного вызова. BeginInvoke возвращает IasyncResult, который можно использовать для контроля выполнения вызова.
39 Метод EndInvoke используется для считывания результата асинхронного вызова. Его можно вызывать в любой момент после BeginInvoke; если асинхронный вызов не завершен, EndInvoke будет блокирован до завершения вызова. Параметры EndInvoke включают параметры out и ref метода, который нужно исполнить асинхронно, и дополнительно IasyncResult, возвращаемый методом BeginInvoke.
40 Четыре основных способа использования BeginInvoke и EndInvoke для выполнения асинхронных вызовов. После вызова BeginInvoke можно: Сделать какую-нибудь работу и затем вызвать EndInvoke для блокировки до тех пор, пока вызов не завершится. Получить WaitHandle с помощью IAsyncResult.AsyncWaitHandle и использовать его метод WaitOne для блокировки исключения до тех пор, пока не поступит сигнал от WaitHandle, а затем вызвать EndInvoke. Производить периодический опрос IasyncResult, возвращаемого методом BeginInvoke, для определения момента завершения асинхронного вызова, и затем вызвать EndInvoke. Передать в BeginInvoke делегат для метода обратного вызова. Этот метод выполняется в потоке ThreadPool при завершении асинхронного вызова, а затем вызывает EndInvoke. Внимание! После завершения асинхронного вызова всегда вызывайте EndInvoke.
41 Ожидание асинхронного вызова с использованием WaitHandle Ожидание WaitHandle это обычный метод синхронизации потоков. Можно получить WaitHandle, используя свойство AsyncWaitHandle интерфейса IAsyncResult, возвращаемого методом BeginInvoke. При завершении асинхронного вызова WaitHandle выставляет сигнал, который можно подождать, вызвав WaitOne. При использовании WaitHandle можно выполнить дополнительные операции после завершения асинхронного вызова и до считывания результата путем вызова EndInvoke.
42 Опрос завершения асинхронного вызова Чтобы определить, когда завершается асинхронный вызов, можно использовать свойство IsCompleted интерфейса IAsyncResult, возвращаемого методом BeginInvoke. Это можно делать, когда асинхронный вызов сделан из потока, обслуживающего пользовательский интерфейс. Периодический опрос завершения позволяет потоку пользовательского интерфейса продолжать обработку ввода данных пользователем.
43 int threadId; public string TestMethod(int callDuration, out int threadId) { Console.WriteLine("Test method begins."); Thread.Sleep(callDuration); threadId = AppDomain.GetCurrentThreadId(); return "MyCallTime was " + callDuration.ToString(); } } // Initiate the asychronous call. IAsyncResult ar = dlgt.BeginInvoke(3000, out threadId, null, null); // Poll while simulating work. while(ar.IsCompleted == false) { Thread.Sleep(10); } // Call EndInvoke to retrieve the results. string ret = dlgt.EndInvoke(out threadId, ar); Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret); }
44 Выполнение метода обратного вызова при завершении асинхронного вызова Если поток, инициировавший асинхронный вызов, не обязательно должен обрабатывать результаты вызова, можно выполнить метод обратного вызова при завершении асинхронного вызова. Чтобы использовать метод обратного вызова, необходимо передать в BeginInvoke делегат AsyncCallback,, предоставляющий этот метод. Можно также передать объект, содержащий данные, которые будут использоваться методом обратного вызова. Например, можно передать делегат, который был использован для инициирования вызова, таким образом, что метод обратного вызова сможет вызвать EndInvoke.
45 Интерфейс IAsyncResult Интерфейс IAsyncResult используется для контроля и управления асинхронной операцией. Он возвращается из начальной операции и передается конечной операции для связи начала и окончания. Если обратный вызов описан как часть операции начала, AsyncResult передается в него
46 Cвойства интерфейса IasyncResult, которые могут быть использованы для контроля состояния асинхронной операции и получения объекта состояния асинхронной операции, передаваемого (необязательно) в начальную операцию: public interface IAsyncResult { Object AsyncState { get; } WaitHandle AsyncWaitHandle { get; } bool CompletedSynchronously { get; } bool IsCompleted { get; } }
47 AsyncState Возвращает объект, который был предоставлен в виде последнего параметра как часть вызова метода начальной операции. AsyncWaitHandle Свойство AsyncWaitHandle возвращает WaitHandle, который может быть использован для выполнения WaitHandle.WaitOne либо WaitAny или WaitAll. Примечание. Объект, реализующий IasyncResult, может не создавать WaitHandle до тех пор, пока не будет считано свойство AsyncWaitHandle; момент его создания находится на усмотрении разработчика. Если разработчик создает WaitHandle, он ответственен за уведомление WaitHandle о прекращении ожидания в соответствующий момент. Например, AsyncResult прекращает ожидание по поручению вызывающего объекта при возврате вызванного асинхронно метода. WaitHandle, будучи созданным, должен существовать до тех пор, пока пользователь не вызовет метод, завершающий асинхронную операцию. В этот момент объект, соответствующий AsyncWaitHandle, может быть удален. CompletedSynchronously Свойство CompletedSynchronously будет иметь значение true, если вызов начальной операции завершится синхронно. IsCompleted Свойство IsCompleted будет иметь значение true после того, как сервер завершит обработку вызова.
48 Делегат AsyncCallback для асинхронных операций Делегат AsyncCallback используется для описания метода, который должен быть вызван по завершении начальной операции. Делегат AsyncCallback передается как второй из последних параметров начальной операции: public delegate void AsyncCallback(IAsyncResult ar);
49 Асинхронные делегаты Асинхронные делегаты позволяют вызывать синхронные методы асинхронно. При синхронном вызове делегата метод Invoke вызывает метод назначения непосредственно в текущий поток. При вызове метода BeginInvoke общеязыковая среда выполнения поставит запрос в очередь и выполнит возврат в вызывающий объект. Метод назначения будет вызван в поток из группы потоков. Исходный поток, отправивший этот запрос, теперь может беспрепятственно продолжать работу параллельно с методом назначения, который работает в потоке группы потоков. Если в BeginInvoke был задан обратный вызов, он будет вызван при возврате метода назначения. В обратном вызове метод EndInvoke используется для получения возвращаемого значения, а также входных и выходных параметров. Если в BeginInvoke обратный вызов не был задан, EndInvoke можно использовать в исходном потоке, отправившем запрос.
50 Список литературы: Рихтер Дж. Программирование на платформе Microsoft.NET Framework Microsoft Corporation Основы Microsoft Visual Studio.NET 2003