
- •Конспект лекций по курсу «Сети эвм» Часть 2 Сурков д.А.
- •Сравнительная характеристика технологий .Net и Java
- •Общее для Java и .Net.
- •Управление памятью в .Net
- •Процедурные типы данных (делегаты)
- •Динамические массивы
- •Многозадачность
- •1: Добавление в очередь ThreadPool нового делегата, который будет запускаться в отдельном потоке (из пула свободного потока). Делегат отработал – поток обратно в пул.
- •Исключительные ситуации
- •Шаблоны в с# (появились недавно в .Net 2.0)
- •В с# в шаблонах введено понятие итератора.
- •Массивы
- •Метод Get в SystemArray
- •Средства удалённого вызова .Net Remoting
- •Пользовательские атрибуты
- •Inherited – будем ли создавать атрибут для наследника.
- •Защищённые информационные системы. Технология “Эльбрус”
- •Защищенная файловая система
Исключительные ситуации
Это понятие внедрено в саму платформу .Net, но по использованию отличается от С:
в C#, Java, Delphi есть блок try…finally. Этот оператор используется в 100 раз чаще, чем try…catch.
В C# есть специальный предопределенный класс Exception, от которого наследуются все остальные исключительные ситуации. Вызываются исключительные ситуации так:
throw new Exception (“Can not access database”);
текст – описание исключительной ситуации – должен быть максимально подробным, написанным без сокращений и членораздельно указывать конкретную причину ошибки, чтобы, получив это сообщение, сразу понять причину.
Для обработки исключительных ситуаций существует try…catch:
try
{
Op1 ( );
Op2 ( );
}
catch (Exception e) // для обработки всех исключений
(
Console.WriteLine (e.Message); // в Message помещается текст из
} // throw new Exception (…);
Обработка каждого сообщения при построении специальных библиотек помещается в try…catch, чтобы в случае исключительной ситуации появилось окно, а дальше продолжилась обработка сообщений. При написании программ используется стандартные процедуры обработки исключительных ситуаций из визуальных библиотек. Надо заботиться о защите от исключительных ситуаций с помощью try…finally. Они используются:
-
когда происходит вход/выход в/из критическую секцию (выход – в finally)
-
освобождение объекта с помощью dispose (конструирование объекта – до try, dispose в finally)
В секции try выполняется любая работа. Создавать объект надо до try, а копировать его внутри:
Object o = new MyObject ( );
try
{
o.Do ( );
}
finally
{
o.Dispose ( );
}
Если возникает исключение в самом конструкторе, то нет для кого вызывать Dispose.
Исключительные ситуации надо программировать при многопоточности. Если исключительная ситуация в потоке, то поток прерывается, прерывается выполнение всей программы, и программа завершается с ошибкой.
Метод потока всегда должен быть защищен от исключительных ситуаций. При использовании пула потоков (ThreadPool), каждый вызываемый делегат дополнительно обрамляется блоком try…catch. При ошибке поток приостанавливается преждевременно, и в его свойстве состояния записывается объект исключения, который возник в потоке. При использовании объектов класса Thread каждый делегат, который передается в thread, надо объявлять с catch (т.е. надо это делать программисту, а при использовании пула система берет на себя).
Object o = null;
try
{
o = new MyObject ( );
o.Do ( );
}
finally
{
o.Dispose ( );
}
Это грубая ошибка, т.к. при ошибке конструктора в о будет null, а потом Dispose будет применяться к o==null (using вызывает Dispose автоматически).
(отступление)
Для volatile-переменных не используется кэширование.
Для volatile-переменных гарантируется чтение/запись за одну машинную операцию. При работе с volatile-переменными могут быть ошибки. Логически переменные читают/записываются за одну операцию, я если переменная занимает много байт, то чтение/запись может выполняться за две инструкции. Если поток читает, то он читает 4 байта, а другие 4 байта не прочитает. Или если пишет другой поток, то может часть записать, а другой не запишет. Поэтому можно использовать критические секции. Но это неэффективно: если вход в критическую секцию, то происходит «ресинхронизация КЭШей процессора» (производится доступ к функции ОС-мы). Вход в критическую секцию занимает намного больше времени (в 1000 раз), чем работа с переменной в критической секции. Доступ к переменной замедляется при рассинхронизации.
Второй подход решения проблемы (без критической секции):
Interlocked XXXX
InterlockedExchange - установка значения
InterlockedRead - чтение
InterlockedIncrement - увеличение на 1
InterlockedDecrement - уменьшение на 1
Обеспечивают атомарное выполнение операций. Эти операции обращаются к ОС, но они не входят в критическую секцию.