- •Сборки (assembly) в среде .Net. Проблема версионности сборок и ее решение.
- •Номер версии в .Net
- •Сведения о версии
- •Номер версии сборки
- •Информационная версия сборки
- •Общая система типов данных в среде .Net. Размерные и ссылочные типы данных. Типы, переменные и значения
- •Пользовательские типы
- •Система общих типов cts
- •Ссылочные типы
- •Типы литеральных значений
- •Неявные типы, анонимные типы и типы, допускающие значение null
- •Упаковка и распаковка размерных типов данных в среде .Net.
- •Производительность
- •Упаковка–преобразование
- •Распаковка-преобразование
- •Ссылочные типы данных. Объектная модель в среде .Net и языке c#.
- •Модели ручной и автоматической утилизации динамической памяти, их сравнительная характеристика. Модель с ручным освобождением памяти
- •Модель с автоматической «сборкой мусора»
- •Модель автоматической утилизации динамической памяти, основанная на сборке мусора. Проблема недетерминизма.
- •Модель автоматической утилизации динамической памяти, основанная на аппаратной поддержке (тегированной памяти).
- •Сборка мусора в среде .Net. Построение графа достижимых объектов.
- •Сборка мусора в среде .Net. Механизм поколений объектов.
- •Модель детерминированного освобождения ресурсов в среде .Net. Интерфейс iDisposable и его совместное использование с завершителем (методом Finalize).
- •«Мягкие ссылки» и кэширование данных в среде .Net.
- •Краткие и длинные слабые ссылки
- •Краткая ссылка
- •Длинная ссылка
- •Правила использования слабых ссылок
- •Динамические массивы в среде .Net и языке c#.
- •Приведение типов в массивах
- •Все массивы неявно реализуют /Enumerable, /Collection и iList
- •Передача и возврат массивов
- •Создание массивов с ненулевой нижней границей
- •Производительность доступа к массиву
- •Небезопасный доступ к массивам и массивы фиксированного размера
- •Делегаты в среде .Net и механизм их работы. Знакомство с делегатами
- •Использование делегатов для обратного вызова статических методов
- •Использование делегатов для обратного вызова экземплярных методов
- •Правда о делегатах
- •Использование делегатов для обратного вызова множественных методов (цепочки делегатов)
- •Поддержка цепочек делегатов в с#
- •Расширенное управление цепочкой делегатов
- •Упрощение синтаксиса работы с делегатами в с#
- •Упрощенный синтаксис № 1: не нужно создавать объект-делегат
- •Упрощенный синтаксис № 2: не нужно определять метод обратного вызова
- •Упрощенный синтаксис № 3: не нужно определять параметры метода обратного вызова
- •Упрощенный синтаксис № 4: не нужно вручную создавать обертку локальных переменных класса для передачи их в метод обратного вызова
- •Делегаты и отражение
- •События в среде .Net; реализация событий посредством делегатов. События
- •Этап 1: определение типа, который будет хранить всю дополнительную информацию, передаваемую получателям уведомления о событии
- •Этап 2: определение члена-события
- •Этап 3: определение метода, ответственного за уведомление зарегистрированных объектов о событии
- •Этап 4: определение метода, транслирующего входную информацию в желаемое событие
- •Как реализуются события
- •Создание типа, отслеживающего событие
- •События и безопасность потоков
- •Явное управление регистрацией событий
- •Конструирование типа с множеством событий
- •Исключительные ситуации и реакция на них в среде .Net. Достоинства
- •Механика обработки исключений
- •Блок try
- •Блок catch
- •Блок finally
- •Генерация исключений
- •Определение собственных классов исключений
- •Исключения в платформе .Net Framework
- •Исключения и традиционные методы обработки ошибок
- •Управление исключениями средой выполнения
- •Фильтрация исключений среды выполнения
- •21 Средства многопоточного программирования в среде .Net. Автономные потоки. Пул потоков.
- •Создание и использование потоков
- •Запуск и остановка потоков
- •Методы управления потоками
- •Безопасные точки
- •Свойства потока
- •Потоки Windows в clr
- •К вопросу об эффективном использовании потоков
- •Пул потоков в clr
- •Ограничение числа потоков в пуле
- •22. Асинхронные операции в среде .Net. Асинхронный вызов делегатов.
- •23. Синхронизация программных потоков в среде .Net. Блокировки.
- •Двойная блокировка
- •Класс ReaderWriterLock
- •Использование объектов ядра Windows в управляемом коде
- •Вызов метода при освобождении одного объекта ядра
- •24. Синхронизация программных потоков в среде .Net. Атомарные (Interlocked-операции). Семейство lnterlocked-методов
- •25. Прерывание программных потоков в среде .Net. Особенности исключительной ситуации класса ThreadAbortException.
- •26. Мониторы в среде .Net. Ожидание выполнения условий с помощью методов Wait и Pulse. Класс Monitor и блоки синхронизации
- •«Отличная» идея
- •Реализация «отличной» идеи
- •Использование класса Monitor для управления блоком синхронизации
- •Способ синхронизации, предлагаемый Microsoft
- •Упрощение кода c# при помощи оператора lock
- •Способ синхронизации статических членов, предлагаемый Microsoft
- •Почему же «отличная» идея оказалась такой неудачной
- •Целостность памяти, временный доступ к памяти и volatile-поля
- •Временная запись и чтение
- •Поддержка volatile-полей в с#
- •27. Асинхронный вызов делегатов.
- •Общие типы (Generics)
- •Инфраструктура обобщений
- •Открытые и закрытые типы
- •Обобщенные типы и наследование
- •Проблемы с идентификацией и тождеством обобщенных типов
- •«Распухание» кода
- •Обобщенные интерфейсы
- •Обобщенные делегаты
- •Обобщенные методы
- •Логический вывод обобщенных методов и типов
- •Обобщения и другие члены
- •Верификация и ограничения
- •Основные ограничения
- •Дополнительные ограничения
- •Ограничения конструктора
- •Другие вопросы верификации
- •Приведение переменной обобщенного типа
- •Присвоение переменной обобщенного типа значения по умолчанию
- •Сравнение переменной обобщенного типа с null
- •Сравнение двух переменных обобщенного типа
- •Использование переменных обобщенного типа в качестве операндов
- •Преимущества использования общих типов
- •29. Итераторы в среде .Net. Создание и использование итераторов.
- •Общие сведения о итераторах
Использование объектов ядра Windows в управляемом коде
Windows предлагает несколько объектов ядра для выполнения синхронизации потоков: мьютексы, семафоры и события. В этом разделе мы поговорим об использовании этих объектов в CLR.
Методы классов Monitor и ReaderWriterLock позволяют выполнять синхронизацию потоков одного домена AppDomain, а объекты ядра можно использовать для синхронизации потоков различных AppDomain или процессов. Поэтому при создании объекта ядра можно задать права доступа, указав, кто и что может делать с этим объектом. Ожидая освобождения объекта ядра, поток должен переходить из пользовательского режима в режим ядра, что сильно снижает производительность. Поэтому синхронизация с использованием объектов ядра — самый медленный из механизмов синхронизации. Он намного медленнее, чем использование класса ReaderWriterLock. Использование объектов ядра в 33 раза медленнее применения методов класса Monitor.
В пространстве имен System.Threading есть абстрактный класс WaitHandle. Это довольно простой класс, единственная задача которого — служить оболочкой описателя объекта ядра. В FCL есть несколько классов, производных от WaitHandle. Все классы определены в пространстве имен System.Threading и реализованы в библиотеке MSCorLib.dll. Исключение — класс Semaphore, который реализован в библиотеке System.dll. Иерархия классов выглядит следующим образом:
WaitHandle
Mutex
Semaphore
EventWaitHandle
AutoResetEvent
ManualResetEvent
В базовом классе WaitHandle есть поле, содержащее Win32-описатель объекта ядра. Это поле инициализируется при конструировании класса, производного от WaitHandle. Кроме этого, класс WaitHandle предоставляет открытые методы, единые для всех производных неабстрактных классов. Приведенное ниже псевдо определение класса описывает все интересные открытые методы класса WaitHandle (не показаны некоторые перегруженные версии отдельных методов):
public abstract class WaitHandle : MarshalByRefObject, IDisposable
{
// Код метода Close вызывает Win32-функцию CloseHandle.
public virtual void Close();
// Код метода WaitOne вызывает Win32-функцию WaitForSingleObjectEx.
public virtual Boolean WaitOne();
public virtual Boolean WaitOne(Int32 millisecondsTimeout, Boolean exitContext);
// Код метода WaitAny вызывает Win32-функцию WaitForMultipleObjectsEx.
public static Int32 WaitAny(WaitHandle[] waitHandles);
public static Int32 WaitAny(WaitHandle[] waitHandles,
Int32 millisecondsTimeout, Boolean exitContext);
// Код метода WaitAll вызывает Win32-функцию WaitForMultipleObjectsEx.
public static Boolean WaitAll(WaitHandle[] waitHandles);
public static Boolean WaitAll(WaitHandle[] waitHandles,
Int32 millisecondsTimeout, Boolean exitContext);
// Код метода SignalAndWait вызывает Win32-функцию SignalObjectAndWait.
public static Boolean SignalAndWait(WaitHandle toSignal, WaitHandle toWaitOn);
public static Boolean SignalAndWait(WaitHandle toSignal,
WaitHandle toWaitOn, Int32 millisecondsTimeout, Boolean exitContext);
public const Int32 WaitTimeout = 0x102;
}
По поводу этих методов есть несколько замечаний:
Можно вызвать метод Close класса WaitHandle (или не имеющий параметров метод Dispose интерфейса IDisposable), чтобы закрыть соответствующий описатель объекта ядра. Внутри этих методов вызывается Win32-функция CloseHandle.
Можно вызвать метод WaitOne класса WaitHandle, чтобы вызывающий поток ожидал освобождения соответствующего объекта ядра. Внутри метода вызывается Win32-функция WaitForSingleObjectEx. Если объект освободился, возвращается значение true. В случае тайм-аута возвращается false.
Можно вызвать метод WaitAny класса WaitHandle, чтобы вызывающий поток ожидал освобождения одного из объектов ядра, указанных в параметре WaitHandle[]. Возвращаемое значение Int32 является индексом элемента массива, соответствующего освободившемуся объекту ядра или WaitHandleWaitTimeout, если за время тайм-аута ни один объект не освободился. Внутри этого метода вызывается Win32-функция WaitForMultipleObjectsEx, передающая в параметре bWaitAllзначение false.
Можно вызвать метод WaitAll класса WaitHandle, чтобы заставить вызывающий поток ожидать освобождения всех объектов ядра, указанных в параметре WaitHandle[]. Если все объекты освобождены, возвращается логическое значение true, в противном случае (не все объекты освобождены) — false. Внутри этого метода вызывается Win32-функция WaitForMultipleObjectsEx, передающая в параметре bWaitAll значение true.
Статический метод SignalAndWait класса WaitHandle вызывается, чтобы атомарно освободить один объект ядра и ожидать освобождения другого объекта. Если объект освободился, возвращается значение true. В случае тайм-аута возвращается false. Внутри этого метода используется Win32-функции SignalObjectAndWait.
Версии WaitOne, WaitAll и SignalAndWait, которые не принимают параметр тайм-аута, должны прототипироваться как возвращающие void, а не Boolean. В противном случае эти методы будут возвращать только значение true, поскольку по умолчанию время ожидания не ограничено. При вызове любого из этих методов проверять возвращаемое значение не нужно.
Версии WaitOne, WaitAll, WaitAny и SignalAndWait, не принимающие параметр exitContext, подставляют в него значение по умолчанию —false. CLR позволяет разместить объект в собственном контексте, применив к классу следующие методы:
System.Runtime.Remotin.Contexts.ContextAttribute
System.Runtime.Remoting.Contexts.SynchronizationAttribute.
Контекст можно сравнить с мини-доменом AppDomain или мини-окружением для экземпляров класса. В любом случае эти атрибуты имеют отношение к удаленному доступу, а использование этих функций сейчас не рекомендуется. При вызове одного из методов класса WaitHandle, принимающего параметр exitContext, обычно передают значение false.
Классы Mutex, Semaphore, AutoResetEvent и ManualResetEvent являются производными от WaitHandle, поэтому наследуют поведение этого родительского класса. В этих классах появились некоторые дополнительные методы, о которых мы сейчас поговорим.
Во-первых, код конструкторов всех этих классов вызывает Win32-функцииCreateMutex,CreateSemaphore,CreateEvent(передаваяfalseв параметреbManualReset) илиCreateEvent(передаваяtrueв параметреbManualReset). Возвращаемый всеми вызовами описатель сохраняется в закрытом поле, определенном в базовом классе WaitHandle.
Во-вторых, в классах Mutex,SemaphoreиEventWaitHandleесть статические методыOpenExisting, их внутренний код вызываетWin32- функцииOpenMutex,OpenSemaphoreилиOpenEvent, передавая аргументstring, в котором указывается существующий именованный объект ядра. Возвращаемый всеми этими методами описатель сохраняется в новом объекте, который и возвращает метод OpenExisting.
Если объекта ядра с указанным именем не существует, генерируется исключение WaitHandleCannotBeOpenedException.
В-третьих, чтобы освободить объект ядра MutexилиSemaphore, нужно вызвать методReleaseMutexиз классаMutexилиRelease— из классаSemaphore. Чтобы установить или сбросить событие объекта ядра с автоматическим или ручным сбросом, нужно вызывать (унаследованные от EventWaitHandle) методы Set или Reset класса AutoResetEvent или ManualResetEvent. Прототипы методов Set или Reset класса EventWaitHandle определяют в качестве возвращаемого типа Boolean, но они всегда возвращают значение true, поэтому нет необходимости писать код, проверяющий возвращаемое этими методами значение.