События являются частным случаем шаблона Inversion of Control (IoC). Традиционный поток управления, вызывающая сторона вызывает метод для вызываемого (как вы предлагаете). С IoC (и, следовательно, событиями) мы меняем элемент управления приложения и вместо того, чтобы сообщать вызываемому, что делать, мы сообщаем вызывающему уведомлять нас, когда происходит что-то, в чем мы заинтересованы.
Рассмотрим случай таймера . Я хочу получать уведомления каждые 5 секунд (скажем). Я не хочу постоянно опрашивать таймер ("время уже пришло? Время пришло? Время пришло?"). Вместо этого я хочу инвертировать управление потоком моего приложения. Я хочу сказать таймеру: «Когда придет время, сообщите мне, вызвав этот метод». Таким образом, управление «инвертируется», вызываемый вызывает метод для вызывающего!
Рассмотрим следующий код ...
using System;
using System.Timers;
namespace TestTimer
{
class Program
{
static void Main(string[] args)
{
// create my timer.
var t = new System.Timers.Timer(1000);
// register for notification
// tell the timer, "when it's time, call TimerGoesOff method"
t.Elapsed += new ElapsedEventHandler( TimerGoesOff );
// start the timer
t.Start();
// wait
Console.ReadLine();
}
// this gets called when the timer goes off
public static void TimerGoesOff(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Time is " + e.SignalTime);
}
}
}
Вместо того, чтобы вызывать метод таймера, чтобы спросить, когда он снова сработает (как вы предлагаете), я говорю ему: «когда вы уйдете, вызовите метод TimerGoesOff». Теперь, вместо того, чтобы просто ждать, пока Таймер сработает, я мог бы поработать. Рассмотрим этот код ...
using System;
using System.Threading;
using System.Timers;
namespace TestTimer
{
class Program
{
static void Main(string[] args)
{
// create my timer.
var t = new System.Timers.Timer(1000);
// register for notification
t.Elapsed += new ElapsedEventHandler( TimerGoesOff );
// start the timer
t.Start();
// do some work while timer is going
new Thread(() => DoWork()).Start();
Console.ReadLine();
}
// this gets called when the timer goes off
public static void TimerGoesOff(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Time is " + e.SignalTime);
}
public static void DoWork()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine( "Working ..." );
Thread.Sleep( 1000 );
}
}
}
}
Теперь я получаю что-то вроде ...
Working ...
The Time is 8/25/2009 1:05:59 PM
Working ...
Working ...
The Time is 8/25/2009 1:06:00 PM
Working ...
The Time is 8/25/2009 1:06:01 PM
Working ...
The Time is 8/25/2009 1:06:02 PM
The Time is 8/25/2009 1:06:03 PM
Я использовал Timer.Elapsed Event , чтобы изменить поток управления моего приложения. Я могу уйти и сделать работу, пока «жду», пока не сработает событие таймера. Это стало возможным благодаря IoC и Events.
Это особенно заметно (хе-хе) в пользовательских интерфейсах. Я не хочу продолжать спрашивать "сделал ли пользователь что-нибудь еще? Пользователь еще что-нибудь сделал?" (так было раньше, когда). Вместо этого я говорю Controls, например, «когда пользователь нажимает на вас, дайте мне знать». Таким образом, я могу уйти и заняться другими замечательными делами и при этом быть отзывчивым к пользователю.