zoukankan      html  css  js  c++  java
  • 【转】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

  • 相关阅读:
    Linux命令之 文件归档管理
    C#总结项目《影院售票系统》编写总结完结篇
    C#总结项目《影院售票系统》编写总结三
    C#中MD5加密
    C#中的序列化与反序列化
    C#总结项目《影院售票系统》编写总结二
    C#总结项目《影院售票系统》编写总结一
    java多线程与线程并发四:线程范围内的共享数据
    java多线程与线程并发三:线程同步通信
    java多线程与线程并发二:线程互斥
  • 原文地址:https://www.cnblogs.com/JuneZhang/p/1983504.html
Copyright © 2011-2022 走看看