Как это работает

Объект, используемый для событий, представляет собой экземпляр класса System.Timers.Timer. При инициализации этого объекта задается интервал времени (в миллисекундах). После того как объект Timer запускается посредством вызова его метода Start() , генерируется последовательность событий, отстоящих друг от друга во времени на заданную величину интервала. Функция Main() инициализирует объект Timer с временным интервалом, равным 100 миллисекундам, поэтому после запуска он генерирует события с частотой 10 раз в секунду:

static void Main(string[] args)

{

Timer myTimer = new Timer (100) ;

Объект Timer обладает событием, которое называется Elapsed (истек интервал), что можно увидеть, воспользовавшись окном Object Browser, представленным на рисунке слева. Сигнатура, необходимая для обработчика рассматриваемого вида событий, соответствует типу делегата System.Timers. ElapsedEventHandler, который является одним из стандартных делегатов, определенных в .NET Framework. Этот делегат может использоваться для функций, обладающих следующей сигнатурой:

void functionName(object source, ElapsedEventArgs e);

Объект Timer передает ссылку на самого себя в первом параметре и экземпляр объекта ElapsedEventArgs — во втором. На данном этапе можно не обращать на эти параметры никакого внимания — позже мы вернемся к их рассмотрению. В нашем коде имеется метод с совпадающей сигнатурой:

static void WriteChar(object source, ElapsedEventArgs e)

{

Console.Write(displayString[counter++ % displayString.Length]);

}

Данный метод использует два статических поля класса Class1 — counter и displayString — для вывода отдельного символа. При каждом вызове этого метода будет выводиться новый символ. Следующая задача — привязать этот обработчик к событию, т. е. подписаться на событие. С этой целью используется оператор + = , который позволяет включить в событие обработчик в виде нового экземпляра делегата, инициализированного с используемым методом обработчика событий:

static void Main(string[] args)

{

Timer myTimer = new Timer (100) ;

myTimer.Tick += new EventHandler(WriteChar);

Эта команда (где используется присущий делегатам странный на вид синтаксис) добавляет обработчик в список обработчиков, вызываемых при возникновении события Elapsed. Можно добавлять в этот список сколь угодно много обработчиков, при этом все они должны удовлетворять требуемому критерию. Каждый из этих обработчиков будет вызываться при наступлении события поочередно. Все, что осталось необходимым выполнить в функции Main(),— это запустить таймер:

myTimer.Start();

Поскольку не нужно, чтобы приложение окончилось до того, как будет обработано хотя бы одно событие, то следует приостановить выполнение функции Main(). Простейшим способом такой приостановки является ожидание ввода пользователя, так как выполнение этой команды не сможет завершиться ранее, чем пользователь введет строку текста и/или нажмет клавишу Enter.

Console.ReadLine();

}

Хотя выполнение метода Main() фактически оказывается остановленным, объект продолжает функционировать. При наступлении очередного события он вызывает описанный метод WriteChar, который выполняется параллельно с с выполнением оператора Console.ReadLine ().