关于什么是委托,委托如何使用,我在这里就不说了。

需要说的:

  1. 委托是函数指针链

  2. 委托的 BeginInvoke

  3. 委托如果出现异常,会如何

如果不知道函数指针,可以继续往下看,我来告诉大家,为何需要委托。

假如在写游戏,有一个人物,他会升级,那么在他升级的时候,需要给他添加潜力值,而判断升级是经验类需要写的。

先写一个经验类。

    核心
    如果当前经验大于最大经验,升级。

但是升级是在经验类里,经验类外的人物不会知道已经升级了,那么如何让人物知道升级?

这时可以使用委托。

     如果当前经验大于最大经验
     调用函数升级

那么函数 升级 如何让人物知道,可以使用一个委托

    升级
    调用委托

于是人物可以添加函数到经验。

    经验.升级=人物.升级

这样,经验的升级就是使用人物的升级,可以使用其他类的函数。

上面没有代码,现在来说个有代码的。

假如需要去寄快递,那么需要找邮递,把东西给他

假设有个邮递,可以寄快递

    class 邮递
    {

        public static Action 寄快递;
    }

委托最好用Action

这里定义委托是,不知道会是哪个快递员会去寄快递,在实际,谁也不知道最后是哪个,快递员可能说不想干了,实际快递太辛苦,大家多体谅。所以不能写函数说,快递A 给 小明去寄,因为不知道小明是不是今天上班。

来写一个 主角 张 ,他需要去寄快递。

    class MrZhang
    {
         public void 寄快递()
         {
            邮递.寄快递();
         }

    }

不知道是谁上班,但是我可以寄快递。

最后,今天来上班的快递员


    快递员 a = new 快递员();
    邮递.寄快递 = a.寄快递;

    class 快递员
    {

         public void 寄快递()
         {

         }
    }

就是快递,所以这就是委托使用。

使用一个函数,不知道他是谁用的,可以使用委托。

如果使用的委托是 多播,那么小心用 BeginInvoke

如果使用 同步,那么多个方法是可以运行

            static void Main(string[] args)
        {
            Action m = M1;
            m += M2;
            m.Invoke();
        }

        private static void M1()
        {
            p();
        }

        private static void M2()
        {
            p();
        }

        private static void p()
        {
            Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
        }

如果使用的BeginInvoke,那么在委托多播使用 BeginInvoke 会报异常 System.ArgumentException:“The delegate must have only one target.”

在一个线程不能同时执行多个方法,使用 BeginInvoke 必须在多个线程,所以可以使用 获得所有方法,然后执行

        static void Main(string[] args)
        {
            Action m = M1;
            m += M2;
            //m.Invoke();
            List<IAsyncResult> list=new List<IAsyncResult>();
            var invtl = m.GetInvocationList().OfType<Action>().ToList();
            foreach (Action temp in invtl)
            {
                list.Add(temp.BeginInvoke((e) => { }, null));
            }

            for (int i = 0; i < invtl.Count(); i++)
            {
                invtl[i].EndInvoke(list[i]);
            }

        }

        private static void M1()
        {
            p();
        }

        private static void M2()
        {
            p();
        }

        private static void p()
        {
            Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
        }

有两个需要知道:

m.GetInvocationList() 得到 Delegate 不能直接执行。

需要转类型,定义是知道他是什么类型,上面使用的是 Action ,所以可以转 Action ,如果是自定义的,那么使用自定义的。

第二,如果使用 BeginInvoke ,在等待时,需要拿到 IAsyncResult 才可以。

    var temp = m.BeginInvoke((e) => { }, null);
    m.EndInvoke(temp);

上面代码:如果要使用 BeginInvoke ,小心 Delegate 是多个函数,不是一个函数,所以使用时,建议使用

            var invtl = m.GetInvocationList().OfType<Action>().ToList();
            foreach (Action temp in invtl)
            {
                list.Add(temp.BeginInvoke((e) => { }, null));
            }

需要把类型换自己的类型。

如果委托发生异常

如果委托方法里没有 try catch,那么如果使用 invoke, 委托是函数指针链,所以会在执行异常退出。

如果使用 BeginInvoke ,那么会在 EndInvoke 退出。

        static void Main(string[] args)
        {
            Action m = M1;
            m += M2;
            //m.Invoke();
            List<IAsyncResult> list=new List<IAsyncResult>();
            var invtl = m.GetInvocationList().OfType<Action>().ToList();
            foreach (Action temp in invtl)
            {
                list.Add(temp.BeginInvoke((e) => { }, null));
            }

            //for (int i = 0; i < invtl.Count(); i++)
            //{
            //    invtl[i].EndInvoke(list[i]);
            //}

        }

        private static void M1()
        {
            p();
            throw new ArgumentException();
        }

        private static void M2()
        {
            p();
            throw new ArgumentException();
        }

        private static void p()
        {
            Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
        }

上面代码没有 EndInvoke 不会有异常,异常发生在别线程,所以不会在Main函数异常。

如果使用 EndInvoke 会在 Main 异常

           static void Main(string[] args)
        {
            Action m = M1;
            m += M2;
            //m.Invoke();
            List<IAsyncResult> list=new List<IAsyncResult>();
            var invtl = m.GetInvocationList().OfType<Action>().ToList();
            foreach (Action temp in invtl)
            {
                list.Add(temp.BeginInvoke((e) => { }, null));
            }

            for (int i = 0; i < invtl.Count(); i++)
            {
                invtl[i].EndInvoke(list[i]);
            }

        }

        private static void M1()
        {
            p();
            throw new ArgumentException();
        }

        private static void M2()
        {
            p();
            throw new ArgumentException();
        }

        private static void p()
        {
            Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
        }

事件

如果事件使用 BeginInvoke 和 委托一样


            _event += (s, e) => M1();
            _event += (s, e) => M2();
            _event?.BeginInvoke(null, null, (e) => { }, null);

     private static EventHandler _event;

异常:System.ArgumentException:“The delegate must have only one target.”

需要和 委托 一样,获得函数指针,执行,如果方法里有异常,那么不会在 Main 方法异常,如果没有使用 End 。

            foreach (var temp in _event.GetInvocationList().OfType<EventHandler>())
            {
                temp.BeginInvoke(null, null, (e) => { }, null);
            }

本文还没写好,如果有问题,请联系我

本文内容属于大量抄袭,代码是自己写,但是抄了代码大神写的,于是羞愧放下他的博客:

http://www.cnblogs.com/free722/archive/2011/04/04/2005275.html

http://stackoverflow.com/questions/25979264/understanding-the-wpf-dispatcher-begininvoke

本文会经常更新,请到原文:http://lindexi.oschina.io/lindexi//post/C-%E5%A7%94%E6%89%98


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

C#委托的更多相关文章

  1. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  2. C#基础篇 - 理解委托和事件

    1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...

  3. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  4. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  5. 9、委托、事件、Lambda

    开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.)   第 ...

  6. iOS 委托与文本输入(内容根据iOS编程编写)

    文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑  JXHypnosisViewController.m 修改  loadView 方法,向  ...

  7. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  8. JavaScript事件代理和委托(Delegation)

    JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...

  9. .NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...

  10. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

随机推荐

  1. 团队作业8——第二次项目冲刺(Beta阶段)5.20

    1.当天站立式会议照片 会议内容: 本次会议为第二次会议 本次会议在陆大楼2楼召开,本次会议内容: ①:检查第一次任务完成情况 ②:做第二次任务的详细分工 ③:规定完成时间是在第三次任务之前 ④:遇到 ...

  2. 201521123013 《Java程序设计》第3周学习总结

    1. 本章学习总结 2. 书面作业 Q1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...

  3. 201521123037 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. java异常继承架构 2. 书面作业 本次PTA作业题集异常 1. 常用异常 题目5-1 1.1 截图你的提交结果( ...

  4. 201521123101 《Java程序设计》第10周学习总结

    1.本周学习总结 2.书面作业 1.finally,题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中finally中捕获异常需要注意什么? finally不管是否捕获到异常,始终会被 ...

  5. php memcache 扩展 php -m 与 phpinfo() 不同

    事情起因,因要升级 openssl(openssl升级这里不表) ,所以在升级后对 php 也进行了从新编译,编译成功. 发现没有安装,memcache 扩展,从新编译安装了一下,显示的安装成功,但是 ...

  6. Android SDK Manager 闪退的解决办法

    (一)方案一 原理:  SDK Manager.exe 通过调用 android-sdk-windows\tools\lib\find_java.bat 确认  java.exe 的路径 启用 cmd ...

  7. Activiti第三篇【连接、排他网关、指定任务处理人、组任务】

    连线 上面我们已将学过了流程变量了,可以在[任务服务.运行时服务.流程开始.完成某个任务时设置流程变量],而我们的连接就是流程变量的实际应用了-. 定义流程图 我们并不是所有的流程都是按一条的路径来走 ...

  8. 【设计模式】module(模块)模式

    写在前面 最近刚接触到设计模式, <head first设计模式>里有一篇文章,是说使用模式的心智, 1.初学者"心智" :"我要为HELLO WORLD找个 ...

  9. 在0~N个数字中,取指定个数的不重复数字,要求这些数字的和为指定值,求所有结果

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  10. [js高手之路] html5 canvas系列教程 - 认识canvas以及基本使用方法

    canvas是html5中引入的一个新元素,俗称画布,既然是画布,当然是用来画图的.canvas技术指的是利用javascript操作canvas元素绘制图形的技术,要使用canvas,一定要浏览器支 ...