您的位置:首页 > 编程语言 > C#

C#学习笔记(十一):事件基础

2006-02-05 16:34 351 查看
事件类似于异常,因为它们都由对象引发。但是它们也有几个重要的区别:其中最重要的区别就是没有处理异常中try...catch类似的结构来处理事件,而是必须订阅它们。订阅一个事件的含义是提供代码,在事件发生时执行这些代码,它们称为事件处理程序。
事件处理程序本身都是简单的函数。对事件处理函数的唯一限制是它必须匹配于事件所要求的签名(返回类型和参数)。这个签名是事件定义的一部分,由一个委托指定。
处理过程:
首先,应用程序创建一个可以引发事件的对象。例如,假定应用程序是一个即时信息传送应用程序,它创建的对象表示一个远程用户的连接。当接收到通过该连接从远程用户传送来的信息时,这个连接对象会引发一个事件。
接着,应用程序订阅事件。为此,即时消息传送应用程序将定义一个函数,该函数可以与事件指定的委托类型一起使用,把这个函数的一个引用传送给事件,而事件的处理函数可以是另一个对象的方法,假定是表示显示设备的对象,当接收到信息时,该方法将显示即时信息。
引发事件后,就通知订阅器。当接收到通过连接对象传送过来的即时消息时,就调用显示设备上的事件处理方法。因为我们使用的是一个标准方法,所以引发事件的对象可以通过参数传送任何相关的信息,这样就大大增加了事件的通用性。
看下面这个例子:
[align=left]using System;[/align]
[align=left]using System.Timers;[/align]
[align=left] [/align]
[align=left]namespace Ch12Ex01[/align]
[align=left]{[/align]
[align=left] /// <summary>[/align]
[align=left] /// Class1 的摘要说明。[/align]
[align=left] /// </summary>[/align]
[align=left] class Class1[/align]
[align=left] {[/align]
[align=left] static int counter = 0;[/align]
[align=left] [/align]
[align=left] static string displayString = "This string will appear one letter at a time.";[/align]
[align=left] [/align]
[align=left] [STAThread][/align]
[align=left] static void Main(string[] args)[/align]
[align=left] {[/align]
[align=left] Timer myTimer = new Timer(100);[/align]
[align=left] myTimer.Elapsed += new ElapsedEventHandler(WriteChar);[/align]
[align=left] myTimer.Start();[/align]
[align=left] Console.ReadLine();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] private static void WriteChar(object sender, ElapsedEventArgs e)[/align]
[align=left] {[/align]
[align=left] if(counter>displayString.Length-1)[/align]
[align=left] return;[/align]
[align=left] Console.Write(displayString[counter++%displayString.Length]);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
用于引发事件的对象是System.Timers.Timer类的一个实例。使用一个时间段来初始化该对象,当使用Start()方法启动Timer对象时,就引发一系列事件,根据指定的时间段来引发事件。
Timer对象有一个Elapsed事件,这个事件要求的事件处理程序签名是System.Timers. ElapsedEventHandler委托类型,该委托是在.NET Framework中定义的标准委托之一,用于与下述签名匹配的函数:
void functionName(object sender, ElapsedEventArgs e)
下一个任务是把这个处理程序与事件关联起来――即订阅它。可以使用+=运算符,给事件添加一个处理程序,其形式是用事件处理程序方法初始化的一个新委托实例:
myTimer.Elapsed += new ElapsedEventHandler(functionName)

下面是如何定义和使用自己的事件。
在定义事件前,必须先定一个委托类型,以用于该事件,这个委托类型指定了事件处理方法必须遵循的签名。
public delegate void MessageHandler(string messageText);
这个委托类型称为MessageHandler,是void函数的签名,它有一个string参数。使用这个参数可以把Connection对象接收过来的即时消息发送给Display对象。
定义了委托后(或者定位现有合适的委托),就可以把事件本身定义为Connection类的一个成员。
[align=left] public class Connection[/align]
[align=left] {[/align]
[align=left] public event MessageHandler MessageArrived;[/align]
给事件命名(这里使用的名称为MessageArrived),用event关键字和要使用的委托类型(前面定义的MessageHandler委托类型)声明它。
以这种方式声明了事件后,就可以引发它,方法是按名称来调用它,就好像它是一个其签名是由委托指定的方法一样。例如使用下面的代码引发这个事件:
MessageArrived("This is a message.");
如果定义该委托不包含任何参数,就可以使用下面的代码:
MessageArrived();
订阅事件的类是Display,它包含一个方法DisplayMessage():
[align=left] public class Display[/align]
[align=left] {[/align]
[align=left] public void DisplayMessage(string message)[/align]
[align=left] {[/align]
[align=left] Console.WriteLine("Message arrived:{0}",message);[/align]
[align=left] }[/align]
[align=left] }[/align]
这个方法匹配于委托类型方法的签名(返回类型和参数),所以可以使用它响应MessageArrived事件。

在进行如下定义后
[align=left] Connection myConnection = new Connection();[/align]
[align=left] Display myDisplay = new Display();[/align]
[align=left] myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage);[/align]
我们就可以看出,为myConnection对象的MessageArrived事件进行初始化时,因为MessageArrived事件是用MessageHandler代理类型定义的(void返回值和string参数),而Display类下的DisplayMessage方法的定义与这个委托类型方法的签名一致,所以可以将这个事件引发后要执行的方法转到这个方法上来。
下面是整个程序用到的源代码:
Connection类
[align=left]using System;[/align]
[align=left]using System.Timers;[/align]
[align=left] [/align]
[align=left]namespace Ch12Ex02[/align]
[align=left]{[/align]
[align=left] public delegate void MessageHandler(string messageText);[/align]
[align=left] [/align]
[align=left] public class Connection[/align]
[align=left] {[/align]
[align=left] public event MessageHandler MessageArrived;[/align]
[align=left] [/align]
[align=left] private Timer pollTimer;[/align]
[align=left] [/align]
[align=left] public Connection()[/align]
[align=left] {[/align]
[align=left] pollTimer = new Timer(100);[/align]
[align=left] pollTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public void Connect()[/align]
[align=left] {[/align]
[align=left] pollTimer.Start();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public void Disconnect()[/align]
[align=left] {[/align]
[align=left] pollTimer.Stop();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] private void CheckForMessage(object source, ElapsedEventArgs e)[/align]
[align=left] {[/align]
[align=left] Console.WriteLine("checking for new message.");[/align]
[align=left] Random random = new Random();[/align]
[align=left] if((random.Next(9) == 0) && (MessageArrived != null))[/align]
[align=left] {[/align]
[align=left] MessageArrived("Hello Mum!");[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
Display类
[align=left]using System;[/align]
[align=left] [/align]
[align=left]namespace Ch12Ex02[/align]
[align=left]{[/align]
[align=left] /// <summary>[/align]
[align=left] /// Display 的摘要说明。[/align]
[align=left] /// </summary>[/align]
[align=left] public class Display[/align]
[align=left] {[/align]
[align=left] public void DisplayMessage(string message)[/align]
[align=left] {[/align]
[align=left] Console.WriteLine("Message arrived:{0}",message);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
Class1类
[align=left]using System;[/align]
[align=left] [/align]
[align=left]namespace Ch12Ex02[/align]
[align=left]{[/align]
[align=left] /// <summary>[/align]
[align=left] /// Class1 的摘要说明。[/align]
[align=left] /// </summary>[/align]
[align=left] class Class1[/align]
[align=left] {[/align]
[align=left] /// <summary>[/align]
[align=left] /// 应用程序的主入口点。[/align]
[align=left] /// </summary>[/align]
[align=left] [STAThread][/align]
[align=left] static void Main(string[] args)[/align]
[align=left] {[/align]
[align=left] Connection myConnection = new Connection();[/align]
[align=left] Display myDisplay = new Display();[/align]
[align=left] myConnection.MessageArrived += new MessageHandler(myDisplay.DisplayMessage);[/align]
[align=left] myConnection.Connect();[/align]
[align=left] Console.ReadLine();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]本文出自 “努力学习的小熊” 博客,转载请与作者联系!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: