• 委托与事件


    1.什么是委托?

      委托是表示方法的类型。

    2.定义委托

    Delegate int Del(int a);  //定义委托
    //定义委托实例
    Del del;                  //Del类型的委托
    EventHandle handle;       //void(object,EventArgs)类型的委托
    Action action;            //void()类型的委托
    Action<int> action;       //泛型委托 void(int)类型的委托
    Func<int> func;           //泛型委托 int()类型的委托
    Func<int,string> func;    //泛型委托 int(string)类型的委托
    

    3.执行委托

    //同步执行,会阻塞线程
    action(args);
    action.Invoke(args);
    //异步执行,不会阻塞线程
    action.BeginInvoke(args);  //EndInvoke(agrs)返回委托执行结果,但是会等待,可通过传入回调函数的方法解决等待问题。
    

    4.什么是事件?

      事件是对委托的封装,类似于private的委托,但在类外部可以使用+=方法注册事件。

      事件的出现可以降低程序的耦合度,事件理应由事件拥有者触发,而public的委托可以在类的外部被调用者触发,事件的特性是能在外部注册,不能触发。

      事件的写法就是在委托前加event关键字

    public event Del del;
    public event Action<int> action;
    public EventHandle<MyEventArgs> Handle;
    

    5.单播委托

      只注册了一个方法,使用=赋值。

    Action action = Method;  //注册委托
    action.Invoke();  //同步执行
    action.beginInvoke(args);  //异步执行

    6.多播委托

      有多个注册方法,使用=/+=注册。

    Action action = Method1;  //注册
    Action action += Method2;  //注册
    action.Invoke();  //同步执行Method1和Method2
    action.BeginInvoke(args);  //异步执行会报错
    //正确的异步执行多播委托方法
    if(action != null)
    {
        Delegete[] list = action.GetInvocationList();  //返回注册列表
        foreach(Delegate del in list)
        {
            Action ac = (Action)del;
            ac.BeginInvoke(args);  
        }
    }
    

    7.带有返回值的委托

      ①单播委托

        action.Invoke()同步执行,

        IAsyncResult ar = action.BeginInvoke(args)异步执行

        int re = action.EndInvoke(ar)得到结果

      ②多播委托

        会返回最后一个委托的值,可通过遍历委托列表解决

        使用GetInvocationList()方法获得委托列表

    8.如何让事件只允许一个方法注册

      解决方法是:将事件写成private,再写一个public的注册方法(使用 = 注册),一个public的取消注册方法(使用 -= 取消注册)  

    private event Action action;
    
    public void Register(Action ac)
    {
            action = ac; //=是关键,覆盖注册
    }
    
    pub void UnRegister(Action ac)
    {
           action -= ac;
    }
    

    9.注册方法(订阅者)执行出现异常怎么处理

      采用try-catch捕获,并用GetInvocationList()获取委托列表分开执行,这样可以保证在一个异常出现时,不回影响其它订阅方法的执行。

    //触发事件的方法
    void Method()
    {
        if(action != null)
        {
            Delegate[] dels = action.GetInvocationList();
            foreach(var del in dels)
            {
                 try
                 { ...执行委托   }
                  catch(..){}
           //这里可以使用同步执行或者异步执行
    //异步执行时,只有在调用EndInvoke方法后才会抛出异常。
    } } }

      

  • 相关阅读:
    基于消息摆渡节点的DTN路由
    A DTN Congestion Mechanism Based on Distributed Storage
    $(formId).autocomplete is not a function
    [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket.
    ajax提交的中文便会变成乱码
    Ajax原理
    Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.init
    JavaScript 无符号位移运算符 >>> 三个大于号 的使用方法
    普通按钮提交
    jsp的一些基本操作
  • 原文地址:https://www.cnblogs.com/lztwj/p/5369687.html
Copyright © 2020-2023  润新知