zoukankan      html  css  js  c++  java
  • 委托和事件的一个例子解读From msdn of Microsoft

    这是msdn上的一个事件和委托的例子。比较适合初步了解事件和委托的关系和实现

    本博客还有一个更好的讲解事件和委托的文章,那个更高级,更全面。

      ----》点击链接  本博客的其他文章委托和事件

    或对象可以通过事件向其他类或对象通知发生的相关事情。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

    在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由控件(如按钮和列表框)引发的事件。可使用 Visual C# 集成开发环境 (IDE) 来浏览控件发布的事件,选择要处理的事件。IDE 会自动添加空事件处理程序方法和订阅事件的代码。  事件概述

    事件具有以下特点:

    • 发行者确定何时引发事件,订户确定执行何种操作来响应该事件。

    • 一个事件可以有多个订户。一个订户可处理来自多个发行者的多个事件。

    • 没有订户的事件永远也不会引发。

    • 事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。

    • 如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。可以利用事件同步线程。

    • 在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的。

    首先应该这样理解事件。事件模式中存在事件发布者和事件订阅者,发布者引发事件,并且通知该事件的订阅者;订阅者知道事件已经触发以后去调用自己相关的事件处理方法。一个事件发布者可以有多个订阅者,一个事件订阅者也可以订阅多个事件发布者;事件发布者仅仅引发,触发事件,至于订阅者怎么处理,响应这些事件都是由订阅者自己来定义和处理的。

    这个列子演示如何将符合标准 .NET Framework 模式的事件添加到您自己的类和结构中。.NET Framework 类库中的所有事件均基于 EventHandler 委托,定义如下: 
    //基于委托模式的事件定义,两个输入参数都是net的标准模式,一个object事件触发者,eventargs事件传递的某些参数,可以自己定义这个参数
    public delegate void EventHandler(object sender, EventArgs e);

    public event EventHandler RaiseCustomEvent;//事件的定义

    /*

    以下是全部。实例代码,

    */

    //这个是事件传递的某些参数,可以自己定义要传递什么数据,但是必须继承EventArgs对象

     public class CustomEventArgs : EventArgs
        {
            public CustomEventArgs(string s)
            {
                message = s;
            }
            private string message;

            public string Message
            {
                get { return message; }
                set { message = value; }
            }
        }

    //定义委托事件。注意其中的两个输入参数。虽然不是强制规定,但这是net标准模式

     public delegate void CustomEventHander(object o,CustomEventArgs args);
    //事件的发布者
        class Publisher
        {

            // 声明事件,事件类型急速委托方法的名字。

            public event CustomEventHander RaiseCustomEvent;
            //事件必须是由发布者引发的,所以发布者必须做某些事情才能引发事件并通知订阅者。这个方法就是事件发布者     要    做的
            public void DoSomething()
            {
                OnRaiseCustomEvent(new CustomEventArgs("Did something"));
            }
            //封装这个引发事件方法,使用protected和virtual可以一定程度上保护这个方法,并使用继承类可以重写这个方法
            protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
            {
                // 这个地方用了RaiseCustomEvent的临时copy,在竞争条件下如果最后一个订阅者没有立即订阅事件这个对象就是null。
                CustomEventHander handler = RaiseCustomEvent;//大家可能注意到这个RaiseCustomEvent也没有实例化,只有一个声明而已。其实这个发布者的RaiseCustomEvent的实例化是在订阅者中实现的。

                // 先检查这个事件是否有订阅者
                if (handler != null)
                {
                    //事件传递参数的组织
                    e.Message += String.Format(" at {0}", DateTime.Now.ToString());

                    // 引发事件
                    handler(this, e);
                }
            }
        }

    //事件订阅者

     public class Subscriber
        {
            private string id;

            public Subscriber(string id, PublisherEventTest publisher)
            {
                this.id = id;

               //发布者的RaiseCustomEvent 其实是在这个地方菜实例化的。
               //这个事件使用订阅者的那个处理方法,由订阅者选择和实现。就是HandleCustomEvent方法了
                publisher.RaiseCustomEvent +=new CustomEventHander(this.HandleCustomEvent );

           }

            void HandleCustomEvent(object sender, CustomEventArgs e)
            {
                Console.WriteLine(id + " received this message: {0}", e.MSG);
            }

        }

    //最后客户端的实现

    Publisher publisher = new Publisher();//发布者
                Subscriber s1 = new Subscriber("1", publisher);//订阅者1
                Subscriber s2 = new Subscriber("2", publisher);//订阅者2

                publisher.DoSomeThing();//发布者引发了事件,并且通知了订阅者,订阅者去分别指向自己的事件响应方法

    输出

    1 received this message: do somethings2010-1-21 11:00:54
    2 received this message: do somethings2010-1-21 11:00:54

    本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。

  • 相关阅读:
    Tensorflow基础教程11:常用模块 tf.data :数据集的构建与预处理
    Tensorflow基础教程10:常用模块 TensorBoard:训练过程可视化
    Tensorflow基础教程9:常用模块 tf.train.Checkpoint 之变量的保存与恢复
    Tensorflow基础教程8:自定义层、损失函数和评估指标
    OC原理之多线程中的锁(一)
    OC原理之多线程(二)
    OC原理之多线程(一)
    OC原理之RunLoop的运行逻辑
    OC原理RunLoop(一)
    前端模块化:CommonJS,AMD,CMD,ES6
  • 原文地址:https://www.cnblogs.com/zjypp/p/2319377.html
Copyright © 2011-2022 走看看