【转】C# 中的事件

事件类似于异常,因为它们都由对象引发。与异常的区别,没有与try...catch...finally类似的结构来处理事件,而必须订阅它们。订阅一个事件的含义是提供代码,在事件发生时候执行这些代码,它们称为事件处理程序。

事件可以有许多订阅的处理程序,在该事件发生时候,这些处理程序都会被调用,其中包括引发该事件的对象所在的类的处理程序,但事件处理程序可能在其他类中。
事件处理程序本身都是简单的函数。对事件处理程序函数的唯一的限制是它必须匹配事件所要求的签名(返回类型和参数)。这个签名是事件定义的一部分,有一个委托指定。

代码
1 class Event1
2 {
3 static int counter = 0;
4 static string displayString = "This string will appear one letter at a time";
5 static void Main(string[] args)
6 {
7 Timer timers = new Timer(100);
8 timers.Elapsed += new ElapsedEventHandler(timers_Elapsed);
9 timers.Start();
10 Console.ReadKey();
11
12 }
13
14 static void timers_Elapsed(object sender, ElapsedEventArgs e)
15 {
16 Console.Write(displayString[counter++ % displayString.Length]);
17 }
18 }

用于引发事件的对象是System.Timers.Timer类的一个实例。使用一个时间段来初始化该对象,当使用Start方法启动Timer对象时,就引发一系列事件,根据指定的时间段来引发事件。Timer对象有一个Elapsed事件,这个事件要求的事件处理程序签名是System.Timers.ElapsedEventHandler委托类型, 该委托是.NET FRAMEWORK中定义的标准委托之一,用于与下述签名匹配的函数
void functionName(object source , ElapsedEventArgs e);

把处理程序与事件关联起来,即订阅它,使用+=运算符,给事件添加一个处理程序,其形式使用事件处理方法初始化的一个新委托的实例。

另外一种理解方式:

1、应用程序创建一个可以引发事件的对象。假定应用程序是一个即时消息传送应用程序,它创建的对象表示一个远程用户的连接。当接收到通过该连接从远程用户传送过来的信息时候,这个连接对象就会引发一个事件。

2、接着,应用程序订阅事件,为此,即时消息传送给应用程序将定义一个函数,该函数可以与事件指定的委托类型一起使用,把这个函数的一个引用传递给事件,而事件的处理函数可以是另一个对象的方法。

3、引发事件后,就通知订阅器,当接收到通过连接对象传递过来的即时消息时候,就调用事件处理方法。

由此例子如下:

代码
namespace Test
{
public delegate void MessageHandle(string messageText);
class Collection
{
public event MessageHandle MessageArrived;
private Timer pollTimer;
public Collection()
{
pollTimer
= new Timer(100);
pollTimer.Elapsed
+=new ElapsedEventHandler(pollTimer_Elapsed);
}
private static Random random = new Random();
public void pollTimer_Elapsed(object source, ElapsedEventArgs e)
{
Console.WriteLine(
"Checking for new messages.");
if (random.Next(9) == 0 && MessageArrived != null)
{
MessageArrived(
"Hello Mum!");
}
}
public void Connect()
{
pollTimer.Start();
}
public void DisConnect()
{
pollTimer.Stop();
}
}
class Display
{
public void DisplayMessage(string message)
{
Console.WriteLine(
"Message arrived :{0}", message);
}
}
class Program
{
static void Main(string[] args)
{
Collection my
= new Collection();
Display my1
= new Display();
my.MessageArrived
+= new MessageHandle(my1.DisplayMessage);
my.Connect();
Console.ReadKey();
}
}
}

由此可见,在定义事件之前,我们必须先定义一个委托类型,来用于这个事件,这个委托类型指定了事件处理方法必须遵循的签名。为此,我们必须使用标准的委托语法。

public delegate void MessageHandle(string messageText);

这个委托的类型是MessageHandle,是void函数的签名,它有一个string参数,使用这个参数可以把Collection对象接收过来的即时消息发送给Display对象。

给事件命名,要使用event关键字和要使用的委托类型声明它。

以这种方式声明了事件后,就可以引发它,方法是按名称来调用它,就好像它是一个其签名是有委托指定的方法一样。

还有一个例子:

代码
1 public class MessageArrivedEventArgs : EventArgs
2 {
3 private string message;
4 public string Message
5 {
6 get { return message; }
7 set { message = value; }
8 }
9 public MessageArrivedEventArgs()
10 {
11 message = "No message sent";
12 }
13 public MessageArrivedEventArgs(string newMessage)
14 {
15 message = newMessage;
16 }
17 }
18 public delegate void MessageHandle(Connection c,MessageArrivedEventArgs e);
19 public class Connection
20 {
21 public event MessageHandle MessageEvent;
22 private string name;
23 public string Name
24 {
25 get { return name; }
26 set { name = value; }
27 }
28 Timer timer;
29 public Connection()
30 {
31 timer = new Timer(100);
32 timer.Elapsed += new ElapsedEventHandler(CheckForMessage);
33 }
34 public void Connect()
35 {
36 timer.Start();
37 }
38 public static Random random = new Random();
39 private void CheckForMessage(object sender, ElapsedEventArgs e)
40 {
41 Console.WriteLine("Checking for new messages.");
42 if (random.Next(9) == 0 && MessageEvent != null)
43 {
44 MessageEvent(this, new MessageArrivedEventArgs("Hello Mum!"));
45 }
46
47 }
48
49 }
50 public class Test
51 {
52 public void Display(Connection source, MessageArrivedEventArgs e)
53 {
54 Console.WriteLine("Message arrived from :{0}", source.Name);
55 Console.WriteLine("Message Text : {0}", e.Message);
56 }
57 }
58 class Program
59 {
60 static void Main(string[] args)
61 {
62 Connection myconn = new Connection();
63 myconn.Name = "First Connection";
64 Connection myconn1 = new Connection();
65 myconn1.Name = "Second Connection";
66 Test t = new Test();
67 myconn.MessageEvent+=new MessageHandle(t.Display);
68 myconn.Connect();
69 myconn1.Connect();
70 Console.ReadKey();
71 }
72 }

 这是扩展。

转自http://www.cnblogs.com/hfliyi/archive/2010/12/27/1918296.html

原文地址:https://www.cnblogs.com/JuneZhang/p/1983504.html