C#引入事件,在以往我们编写程序中,往往采用等待机制,为了等待某件事情的发生,需要不断地检测某些判断变量,而引入事件编程后,大大简化了这种过程,事件驱动程序与过程式程序最大的不同就在于,程序不再不停地检查输入设备,而是呆着不动,等待消息的到来,每个输入的消息会被排进队列,等待程序处理它。如果没有消息在等待,则程序会把控制交回给操作系统,以运行其他程序。
- 要想快速理解C#的事件机制,那么你必须先熟悉代理(delegate),定义代理一般步骤如下:
1.创建代理
public delegate int MyDelegate(方法的形参);
2.创建delegate对象,并将你想要传递的函数作为参数传入。
MyDelegate myDelegate = new MyDelegate(实例名.方法名);
3.调用代理
myDelegate(方法的实参);
- 其中,步骤2我们还可以这样写:
A.创建delegate对象
MyDelegate myDelegate = new MyDelegate(实例名.方法名1);
或:MyDelegate myDelegate;
B.在原有的方法的委托实例中再封装进一个新的方法
myDelegate+=new MyDelegate(实例名.方法名2);
其实事件和代理是一样的,我们可以用定义代理的方法来理解事件机制,下面列举一个完整的例子:
创建一个委托
public delegate void KeyDownHandler( object sender, KeyEventArgs e );
在这里面有两个参数, 此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。
定义参数KeyEventArgs类
我们示例中键盘按键事件中要包含按键信息,所以要派生一个KeyEventArgs类,来保存按键信息,好让后面知道按了哪个键。
internal class KeyEventArgs : EventArgs//按键信息
{
private char keyChar;
public KeyEventArgs( char keyChar )
{
this.keyChar = keyChar;
}
}
定义事件类(事件发生类)
我们可以定义一个事件类,在该类中包含事件成员,以及引发事件的属性或方法
//事件发生方
class KeyInputMonitor
{
//定义事件(和定义代理一样)
public event KeyDownEventHandler KeyDown;
//定义引发事件的方法
public void Run()
{
bool finished = false;
do
{
Console.WriteLine("Input a char");
string response = Console.ReadLine();
char responseChar = (response == "") ? ' ' : char.ToUpper(response[0]);
switch (responseChar)
{
case 'X':
finished = true;
break;
default:
//得到按键信息的参数
KeyEventArgs keyEventArgs = new KeyEventArgs(responseChar);
//触发事件
KeyDown(this, keyEventArgs);
break;
}
} while (!finished);
}
应用程序类(事件接受类)
该类包含了类似winform内用户编写的内容,他包含注册事件和事件代理的方法
//事件接收方
class EventReceiver
{
public EventReceiver(KeyInputMonitor monitor)
{
//产生一个委托实例并添加到KeyInputMonitor产生的事件列表中
monitor.KeyDown += new KeyDownEventHandler(this.Echo);
}
//事件需要处理的函数
private void Echo(object sender, KeyEventArgs e)
{
Console.WriteLine("Capture key:{0}", e.KeyChar);
}
}
事件的使用方法
//主程序运行
class MainEntryPoint
{
static void Main()
{
//实例化一个事件发送方
KeyInputMonitor monitor = new KeyInputMonitor();
//实例化一个事件接收方
EventReceiver eventReceiver = new EventReceiver(monitor);
//运行
monitor.Run();
}
}