- •Сборки (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. Создание и использование итераторов.
- •Общие сведения о итераторах
Вызов метода при освобождении одного объекта ядра
Исследуя производительность, специалисты Microsoft обнаружили, что во многих приложениях создают потоки, которые просто ожидают освобождения одного объекта ядра. При освобождении объекта поток направляет определенное уведомление другому потоку, после чего опять ожидает освобождения объекта. Некоторые разработчики даже пишут код, в котором несколько потоков ожидает освобождения объекта. Это очень нерациональная трата системных ресурсов. Так что, если у вас есть потоки, ожидающие освобождения одного объекта ядра, и в этот раз лучшим решением для повышения производительности приложения будет использование пула потоков.
Чтобы поток из пула потоков вызывал нужный метод обратного вызова при освобождении объекта ядра, нужно вызвать статический метод RegisterWaitForSingleObject класса System.Threading.ThreadPool. Есть несколько перегруженных версий этого метода, но все они очень похожи. Вот прототип одной из наиболее часто используемых перегруженных версий:
public static RegisterWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callback,
Object state,
Int32 millisecondsTimeoutlnterval,
Boolean executeOnlyOnce
);
При вызове этого метода аргумент waitObject указывает объект ядра, освобождения которого должен ожидать пул потоков. Поскольку этот параметр унаследован от абстрактного класса WaitHandle, можно указать любой производный от него класс. В частности, можно передать ссылку на объект Semaphore, Mutex, AutoResetEvent или ManualResetEvent. Второй параметр, callback, указывает метод, который поток из пула потоков должен вызывать. Вызываемый метод должен соответствовать делегату System.Threading.WaitOrTimerCallback, который определяется следующим образом:
public delegate void WaitOrTimerCallback(Object state, Boolean timedOut);
Третий параметр метода RegisterWaitForSingleObject, state, позволяет указать некоторые данные состояния, которые нужно передать в метод обратного вызова, когда поток из пула потоков вызывает его. Если данных нет, передайте null. Четвертый параметр, millisecondsTimeoutlnterval, указывает пулу, как долго он должен ожидать освобождения объекта ядра. Чтобы задать неограниченное время ожидания, обычно передают Timeout Infinite или -1. Если последний параметр, executeOnlyOnce, равен true, пул потоков выполнит метод обратного вызова только раз.
Если же executeOnlyOnce равен false, поток из пула потоков будет выполнять метод обратного вызова при каждом освобождении объекта ядра. Это исключительно удобно при ожидании освобождения объекта AutoResetEvent.
Методу обратного вызова передаются данные состояния и логическое значение timedOut. Если timedOut равен false, метод знает, что он вызван по причине освобождения объекта ядра. Если же значение timedOut равно true, метод знает, что он вызывается потому, что объект ядра не освободился за означенное время. Метод обратного вызова может выполнять любые операции, причем выбор операции может зависеть от значения, полученного в аргументе timedOut.
Метод RegisterWaitForSingleObject возвращает ссылку на объект RegisteredWaitHandle. Последний определяет объект ядра, освобождения которого ожидает пул потоков. Если по какой-то причине приложение должно сообщить пулу потоков, что нужно прекратить наблюдение за ожидаемым описателем, вызывают метод Unregister класса RegisteredWaitHandle:
public Boolean Unregister(WaitHandle waitObject);
Значение параметра waitObject указывает, как нужно вернуть уведомление о выполнении всех рабочих элементов в очереди зарегистрированного объекта ожидания. Если уведомление не требуется, передайте null. Если надо передать корректную ссылку на объект, производный от класса WaitHandle, пул потоков сообщит объекту о выполнении всех рабочих элементов.
Приведенный ниже пример кода показывает, как поток из пула потоков вызывает метод каждый раз, когда освобождается объект AutoResetEvent:
using System;
using System.Threading;
public static class Program
{
public static void Main()
{
// Создание объекта AutoResetEvent (изначально не освобожденного).
AutoResetEvent are = new AutoResetEvent(false);
// Сообщаем пулу потоков, что нужно ожидать AutoResetEvent.
RegisteredWaitHandle rwh = ThreadPool.RegisterWaitForSingleObject(
are, // Ожидать этот объект AutoResetEvent.
EventOperation, // Выполнить обратный вызов этого метода.
null, // Передать null в качестве параметра EventOperation.
5000, // Ждать освобождения 5 секунд.
false); // Вызывать EventOperation при каждом освобождении.
// Запуск цикла.
Char operation;
do
{
Console.WriteLine("S=Signal, Q=Quit?");
operation = Char.ToUpper(Console.ReadKey(true).KeyChar);
if (operation == 'S')
{
// Пользователь хочет освободить событие; устанавливаем событие.
are.Set();
}
}
while (operation != 'Q');
// Сообщаем пулу потоков, что нужно прекратить ожидание события.
rwh.Unregister(null);
}
// Этот метод вызывается при каждом освобождении события или
// через 5 секунд после последнего освобождения/тайм-аута,
private static void EventOperation(Object state, Boolean timedOut)
{
if (timedOut)
{
Console.WriteLine("Timedout while waiting for the AutoResetEvent.");
}
else
{
Console.WriteLine("The AutoResetEvent became signaled.");
}
}
}