Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
15
Добавлен:
02.11.2018
Размер:
626.37 Кб
Скачать

2.33. Диагностика

В данном параграфе будут рассмотрены средства, облегчающие диагностику проблем и мониторинг поведения приложения.

Описание средств диагностики начнём с условной компиляции, выполняемой при помощи специальных препроцессорных директив. Препроцессорные директивы – это инструкции для компилятора, начинающиеся с символа # и расположенные в отдельной строке кода. Директива #if заставляет компилятор проигнорировать фрагмент кода, если описан символ, указанный после #if. Для описания символа служит препроцессорная директива #define.

#define TESTMODE // #define должна стоять в начале фала

using System;

public class Program

{

private static void Main(string[] args)

{

#if TESTMODE

Console.WriteLine("in test mode!");

#endif

}

}

Символ можно описать не только с помощью #define, но и указав ключ компилятора командной строки /define или используя окно свойств проекта в Visual Studio (в этих случаях описание символа распространяется не на отдельный файл, а на всю сборку). При условной компиляции можно применять также директивы #else, #elif (комбинация #else и #if), знаки &&, ||, ! и директиву #undef (для отмены в отдельном файле символа сборки).

#define V2

#define TestMode

using TestType =

#if V2 && TestMode

MyCompany.GadgetV2;

#else

MyCompany.Gadget;

#endif

Метод класса1 может быть помечен атрибутом [Conditional] с указанием символа. В этом случае компилятор исключит из кода все вызовы помеченного метода, если символ будет не определён.

[Conditional("DEBUG_MODE")]

private void WriteLog(string ms) { . . . }

По сути, использование для метода атрибута [Conditional] аналогично обрамлению каждого вызова метода директивами #if-#endif.

При мониторинге работы программы полезным оказывается возможность вывода и фиксации различных диагностических сообщений. Для этой цели можно применить статические классы Debug и Trace из пространства имён System.Diagnostics. Эти классы очень похожи, но все методы класса Debug помечены атрибутом [Conditional("DEBUG")], а все методы класса Trace – атрибутом [Conditional("TRACE")]. Visual Studio определяет в отладочной конфигурации и DEBUG, и TRACE, а в выпускной конфигурации только TRACE.

Классы Debug и Trace содержат методы вывода сообщений Write(), WriteLine(), WriteIf(), Fail() и Assert(). В классе Trace определены дополнительные методы TraceInformation(), TraceWarning() и TraceError().

Debug.WriteLine("Debug message");

Debug.WriteIf(5 > 2, "Correct condition");

Debug.Fail("Error in code");

Debug.Assert(3 < 2, "Error in condition");

Trace.TraceInformation("Info");

Классы Debug и Trace имеют свойство Listeners, содержащее коллекцию объектов TraceListener. Эти объекты ответственны за обработку содержимого, генерируемого методами вывода сообщений. По умолчанию коллекция Listeners включает один слушатель – объект класса DefaultTraceListener. Этот слушатель записывает сообщения в окно отладчика Visual Studio, а при вызове метода Fail() или нарушении условия в методе Assert() выводит диалоговое окно для подтверждения выполнения программы. Это поведение можно изменить, удалив слушатель или добавив один или несколько собственных. Слушатель можно разработать, унаследовав от TraceListener, или воспользоваться одним из готовых типов:

  • TextWriteTraceListener – пишет в поток, или в TextWriter, или в файл. Имеет подклассы ConsoleTraceListener, DelimitedListTraceListener, XmlWriterTraceListener, EventSchemaTraceListener;

  • EventLogTraceListener – пишет в журнал событий Windows;

  • EventProviderTraceListener – пишет в подсистему ETW в Windows Vista;

  • WebPageTraceListener – пишет на веб-страницу ASP.NET.

При использовании журнала событий Windows сообщения, выводимые методами TraceWarning() и TraceError(), выводятся как предупреждения и ошибки соответственно.

// удаляем слушатель по умолчанию

Trace.Listeners.Clear();

// добавляем слушатель для записи в конец файла

Trace.Listeners.Add(new TextWriterTraceListener("trace.txt"));

// настраиваем журнал событий Windows

if(!EventLog.SourceExists("DemoApp"))

EventLog.CreateEventSource("DemoApp", "Application");

// и добавляем соответсвующий слушатель

Trace.Listeners.Add(new EventLogTraceListener("DemoApp"));

// пишем несколько сообщений

Trace.WriteLine("message");

Trace.TraceError("error");

В классе TraceListener определено свойство Filter, которое можно установить для фильтрации сообщений. Кроме этого, имеется несколько свойств для управления внешним видом выводимых сообщений.

var listener = new TextWriterTraceListener("trace.txt");

listener.Filter = new SourceFilter("Program");

listener.IndentSize = 4;

Для слушателей, которые пишут информацию в кэшируемый поток (например, слушатель TextWriteTraceListener), рекомендуется перед окончанием приложения вызывать методы Close() или Flash(). Такие же методы есть у классов Debug и Trace. Если у этих классов установить свойство AutoFlash в true, то метод Flash() будет вызываться после каждого сообщения.

В заключение отметим, что настройка слушателей может быть выполнена не только программно, но и декларативно – с использование конфигурационного файла приложения (секция <system.diagnostics>).

1 Это значение должно иметь целое количество минут.

1 Некоторые символы Unicode представлены двумя 16-битными «суррогатными» символами.

1 Подробнее см. http://ru.wikipedia.org/wiki/Регулярные_выражения.

1 К базовым типам платформы .NET относятся все числовые типы, а также bool, string и System.DateTime.

1 Типы CultureInfo, NumberFormatInfo, DateTimeFormatInfo определены в пространстве имён System.Globalization.

2 var nfi = (NumberFormatInfo)formatProvider.GetFormat(typeof(NumberFormatInfo));

1 Типы, переопределяющие Equals(), должны также перекрывать метод GetHashCode(); в противном случае коллекции-словари могут работать неправильно.

1 Вот почему тип string не перегружает операции < и > ‑ результат может измениться в зависимости от текущих региональных стандартов.

1 Сборка мусора также происходит и при окончании работы программы.

1 Если начался процесс сборки мусора, любой поток выполнения может продолжать работу до операции размещения или освобождения объекта. После этого поток выполнения приостанавливается, пока сборка мусора не будет закончена.

1 Если бы использовалось foreach (var s in shop), то тип s был бы object.

1 В пространстве имен System.Collections имеется слаботипизированный аналог класса List<T> – класс ArrayList.

1 В пространстве имен System.Collections имеются слаботипизированные аналоги классов Queue<T> и Stack<T> – классы Queue и Stack.

1 В пространстве имен System.Collections имеется слаботипизированный аналог класса Dictionary<TKey,TValue> – класс Hashtable.

1 В пространстве имен System.Collections имеется слаботипизированный аналог класса Collection<T> – класс CollectionBase.

1 Для использования System.Linq необходимо подключить сборку System.Core.dll.

1 Все операторы LINQ имеют модификаторы public static. Для краткости эти модификаторы не указываются.

1 Сами адаптеры потоками не являются.

1 Список не является полным – представлены наиболее часто используемые классы.

1 Заметим, что класс FileStream уже обладает некоторой поддержкой буферизации.

1 При добавлении объектов типа XAttribute или унаследованных от XNode выполняется клонирование, если эти объекты уже имеют родителя в дереве объектов XML.

1 Запись + XName name означает наличие перегруженной версии, принимающей параметр name типа XName.

1 Запись + params означает наличие перегруженной версии, принимающей параметр типа params object[].

1 У XmlTextReader имеются также специфичные методы чтения конкретного содержимого XML-документа (например, ReadContentAsInt(), ReadAttributeValue()).

1 О синтаксисе применения атрибутов и операторе typeof рассказано далее.

1 SOAP (Simple object access protocol) – формат данных, основанный на XML. Применяется для передачи информации в глобальной сети.

1 Класс StreamingContext описывает контекст потока сериализации. Основным свойством класса является State, принимающее значения из перечисления StreamingContextStates.

1 Эти атрибуты размещены в пространстве имён System.Runtime.Serialization и одноимённой сборке.

2 Это необязательное условие при использовании NetDataContractSerializer.

1 Visual Studio не позволяет работать с многофайловыми сборками, поэтому файлы примера придется компилировать, используя компилятор командной строки csc.exe.

1 Технология зондирования сборок (probing) позволяет размещать зависимые сборки в подкаталогах.

1 Об атрибутах будет рассказано в следующих параграфах.

1 Статический метод Activator.CreateInstance() также выполняет создание объектов.

1 Если атрибут применяется к сборке или модулю, он должен быть записан после директив using, но перед основным кодом.

1 Данные требования не продиктованы исполняющей средой, но заложены в компиляторы языков для .NET.

1 Если бы создавался только один объект, соответствующий атрибуту, то изменение данных в нем отразилось бы на всех запросах к атрибуту.

1 В случае веб-приложения файл конфигурации всегда называется web.config.

1 В веб-приложениях используется System.Web.Configuration.WebConfigurationManager.

1 Любой созданный поток резервирует примерно один мегабайт памяти под свои нужды.

1 Прекращение работы фонового потока не гарантируется выполнение его блоков finally.

1 Оба метода – Suspend() и Resume() – помечены как устаревшие. Использовать их не рекомендуется.

1 public delegate void WaitCallback(object state);

1 Существует класс CountdownEvent, посылающий сигнал Set() при достижении внутренним счётчиком заданного значения (метод AddCount() увеличивает счётчик).

1 В приложениях, интенсивно использующих параллелизм, рекомендуется в файле конфигурации указать серверный вариант алгоритма работы сборщика мусора:<configuration>

<runtime>

<gcServer enabled="true" />

</runtime>

</configuration>

1 Вариант реализации данного шаблона был представлен в предыдущем параграфе.

1 Нельзя вызвать асинхронно объект группового делегата.

1 Настройка роли пользователя в Windows соответствует отнесению этого пользователя к одной из групп. Настройка групп выполняется командами Панель управленияАдминистрированиеУправление компьютеромЛокальные пользователи и группы.

1 Существует класс (и атрибут) для разрешений, использующих данные принципала ‑ PrincipalPermission. Так можно разрешить вызов метода определённому пользователю:[PrincipalPermission(SecurityAction.Demand, Name = "Alex")]

private void ActionWithFiles() { . . . }

1 В частности, не затрагиваются вопросы генерации и сохранения ключей шифрования.

1 Или класс, производный от System.Attribute.