事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发事件的对象称为事件发送方。捕获事件并对其作出响应的对象叫做事件接收方。
在事件通信中,事件发送方类不知道哪个对象或方法将接收到(处理)它引发的事件。所需要的是在源和接收方之间存在一个媒介(或类似指针的机制)。.NET Framework 定义了一个特殊的类型(Delegate),该类型提供函数指针的功能。
委托是可保存对方法的引用的类。与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用。这样,委托就等效于一个类型安全函数指针或一个回调。虽然委托具有许多其他的用途,但这里只讨论委托的事件处理功能。一个委托声明足以定义一个委托类。声明提供委托的签名,公共语言运行库提供实现。下面的示例显示了事件委托声明。
只有当事件生成事件数据时才需要自定义事件委托。许多事件,包括一些用户界面事件(例如鼠标单击)在内,都不生成事件数据。在这种情况下,类库中为无数据事件提供的事件委托 System.EventHandler 便足够了。
下面的示例程序阐释如何在一个类中引发一个事件,然后在另一个类中处理该事件。AlarmClock 类定义公共事件 Alarm,并提供引发该事件的方法。AlarmEventArgs 类派生自 EventArgs,并定义 Alarm 事件特定的数据。WakeMeUp 类定义处理 Alarm 事件的 AlarmRang 方法。AlarmDriver 类一起使用类,将使用 WakeMeUp 的 AlarmRang 方法设置为处理 AlarmClock 的 Alarm 事件。
// EventSample.cs.
//
namespace EventSample
{
using System;
using System.ComponentModel;
// Class that contains the data for
// the alarm event. Derives from System.EventArgs.
// 包含警报事件数据的类,从System.EventArgs继承
public class AlarmEventArgs : EventArgs
{
private readonly bool snoozePressed;
private readonly int nrings;
// 构造函数.
//
public AlarmEventArgs(bool snoozePressed, int nrings)
{
this.snoozePressed = snoozePressed;
this.nrings = nrings;
}
// The NumRings property returns the number of rings
// that the alarm clock has sounded when the alarm event
// is generated.
// 当闹铃事件发生时,闹钟响的次数
public int NumRings
{
get { return nrings; }
}
// The SnoozePressed property indicates whether the snooze
// button is pressed on the alarm when the alarm event is generated.
// 当闹铃事件发生时,闹钟的按钮被按下,就停止闹铃
public bool SnoozePressed
{
get { return snoozePressed; }
}
// The AlarmText property that contains the wake-up message.
// 唤醒语言
public string AlarmText
{
get
{
if (snoozePressed)
{
return ("Wake Up!!! Snooze time is over.");
}
else
{
return ("Wake Up!");
}
}
}
}
// Delegate declaration.
// 委托声明
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
// The Alarm class that raises the alarm event.
// 产生闹钟事件的闹钟类
public class AlarmClock
{
private bool snoozePressed = false;
private int nrings = 0;
private bool stop = false;
// The Stop property indicates whether the
// alarm should be turned off.
// 停止属性说明闹钟是否被关闭
public bool Stop
{
get { return stop; }
set { stop = value; }
}
// The SnoozePressed property indicates whether the snooze
// button is pressed on the alarm when the alarm event is generated.
// SnoozePressed属性说明当闹铃时间发生时,snooze button 是否被按下
public bool SnoozePressed
{
get { return snoozePressed; }
set { snoozePressed = value; }
}
// The event member that is of type AlarmEventHandler.
// AlarmEventHandler类型的事件成员
public event AlarmEventHandler Alarm;
// The protected OnAlarm method raises the event by invoking
// the delegates. The sender is always this, the current instance
// of the class.
// 受保护的OnAlarm方法通过激发委托产生事件。发生方就是当前的类事例。
protected virtual void OnAlarm(AlarmEventArgs e)
{
if (Alarm != null)
{
// Invokes the delegates.
// 唤醒委托
Alarm(this, e);
}
}
// This alarm clock does not have
// a user interface.
// To simulate the alarm mechanism it has a loop
// that raises the alarm event at every iteration
// with a time delay of 300 milliseconds,
// if snooze is not pressed. If snooze is pressed,
// the time delay is 1000 milliseconds.
// 闹铃没有用户接口。为了激发闹铃机制,采用循环机制模拟。
public void Start()
{
for (; ; )
{
nrings++;
if (stop)
{
break;
}
else if (snoozePressed)
{
System.Threading.Thread.Sleep(1000);
{
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
else
{
System.Threading.Thread.Sleep(300);
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
}
}
// The WakeMeUp class has a method AlarmRang that handles the
// alarm event.
// WakeMeUp类的AlarmRang方法操作闹铃事件
public class WakeMeUp
{
public void AlarmRang(object sender, AlarmEventArgs e)
{
Console.WriteLine(e.AlarmText + "\n");
if (!(e.SnoozePressed))
{
if (e.NumRings % 10 == 0)
{
Console.WriteLine(" Let alarm ring? Enter Y");
Console.WriteLine(" Press Snooze? Enter N");
Console.WriteLine(" Stop Alarm? Enter Q");
String input = Console.ReadLine();
if (input.Equals("Y") || input.Equals("y")) return;
else if (input.Equals("N") || input.Equals("n"))
{
((AlarmClock)sender).SnoozePressed = true;
return;
}
else
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
else
//
namespace EventSample
{
using System;
using System.ComponentModel;
// Class that contains the data for
// the alarm event. Derives from System.EventArgs.
// 包含警报事件数据的类,从System.EventArgs继承
public class AlarmEventArgs : EventArgs
{
private readonly bool snoozePressed;
private readonly int nrings;
// 构造函数.
//
public AlarmEventArgs(bool snoozePressed, int nrings)
{
this.snoozePressed = snoozePressed;
this.nrings = nrings;
}
// The NumRings property returns the number of rings
// that the alarm clock has sounded when the alarm event
// is generated.
// 当闹铃事件发生时,闹钟响的次数
public int NumRings
{
get { return nrings; }
}
// The SnoozePressed property indicates whether the snooze
// button is pressed on the alarm when the alarm event is generated.
// 当闹铃事件发生时,闹钟的按钮被按下,就停止闹铃
public bool SnoozePressed
{
get { return snoozePressed; }
}
// The AlarmText property that contains the wake-up message.
// 唤醒语言
public string AlarmText
{
get
{
if (snoozePressed)
{
return ("Wake Up!!! Snooze time is over.");
}
else
{
return ("Wake Up!");
}
}
}
}
// Delegate declaration.
// 委托声明
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
// The Alarm class that raises the alarm event.
// 产生闹钟事件的闹钟类
public class AlarmClock
{
private bool snoozePressed = false;
private int nrings = 0;
private bool stop = false;
// The Stop property indicates whether the
// alarm should be turned off.
// 停止属性说明闹钟是否被关闭
public bool Stop
{
get { return stop; }
set { stop = value; }
}
// The SnoozePressed property indicates whether the snooze
// button is pressed on the alarm when the alarm event is generated.
// SnoozePressed属性说明当闹铃时间发生时,snooze button 是否被按下
public bool SnoozePressed
{
get { return snoozePressed; }
set { snoozePressed = value; }
}
// The event member that is of type AlarmEventHandler.
// AlarmEventHandler类型的事件成员
public event AlarmEventHandler Alarm;
// The protected OnAlarm method raises the event by invoking
// the delegates. The sender is always this, the current instance
// of the class.
// 受保护的OnAlarm方法通过激发委托产生事件。发生方就是当前的类事例。
protected virtual void OnAlarm(AlarmEventArgs e)
{
if (Alarm != null)
{
// Invokes the delegates.
// 唤醒委托
Alarm(this, e);
}
}
// This alarm clock does not have
// a user interface.
// To simulate the alarm mechanism it has a loop
// that raises the alarm event at every iteration
// with a time delay of 300 milliseconds,
// if snooze is not pressed. If snooze is pressed,
// the time delay is 1000 milliseconds.
// 闹铃没有用户接口。为了激发闹铃机制,采用循环机制模拟。
public void Start()
{
for (; ; )
{
nrings++;
if (stop)
{
break;
}
else if (snoozePressed)
{
System.Threading.Thread.Sleep(1000);
{
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
else
{
System.Threading.Thread.Sleep(300);
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
}
}
// The WakeMeUp class has a method AlarmRang that handles the
// alarm event.
// WakeMeUp类的AlarmRang方法操作闹铃事件
public class WakeMeUp
{
public void AlarmRang(object sender, AlarmEventArgs e)
{
Console.WriteLine(e.AlarmText + "\n");
if (!(e.SnoozePressed))
{
if (e.NumRings % 10 == 0)
{
Console.WriteLine(" Let alarm ring? Enter Y");
Console.WriteLine(" Press Snooze? Enter N");
Console.WriteLine(" Stop Alarm? Enter Q");
String input = Console.ReadLine();
if (input.Equals("Y") || input.Equals("y")) return;
else if (input.Equals("N") || input.Equals("n"))
{
((AlarmClock)sender).SnoozePressed = true;
return;
}
else
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
else